forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
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
....@@ -536,6 +543,10 @@
536543 case IPL_TYPE_FCP_DUMP:
537544 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
538545 break;
546
+ case IPL_TYPE_NVME:
547
+ case IPL_TYPE_NVME_DUMP:
548
+ rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nvme_attr_group);
549
+ break;
539550 default:
540551 rc = sysfs_create_group(&ipl_kset->kobj,
541552 &ipl_unknown_attr_group);
....@@ -564,7 +575,7 @@
564575 {
565576 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
566577
567
- reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
578
+ ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
568579 return sprintf(page, "%s\n", vmparm);
569580 }
570581
....@@ -587,14 +598,14 @@
587598 if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
588599 return -EINVAL;
589600
590
- memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
591
- ipb->ipl_info.ccw.vm_parm_len = ip_len;
601
+ memset(ipb->ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
602
+ ipb->ccw.vm_parm_len = ip_len;
592603 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);
604
+ ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
605
+ memcpy(ipb->ccw.vm_parm, buf, ip_len);
606
+ ASCEBC(ipb->ccw.vm_parm, ip_len);
596607 } else {
597
- ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
608
+ ipb->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_VP;
598609 }
599610
600611 return len;
....@@ -641,8 +652,8 @@
641652 struct bin_attribute *attr,
642653 char *buf, loff_t off, size_t count)
643654 {
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;
655
+ size_t size = reipl_block_fcp->fcp.scp_data_len;
656
+ void *scp_data = reipl_block_fcp->fcp.scp_data;
646657
647658 return memory_read_from_buffer(buf, count, &off, scp_data, size);
648659 }
....@@ -658,17 +669,17 @@
658669 if (off)
659670 return -EINVAL;
660671
661
- memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf, count);
672
+ memcpy(reipl_block_fcp->fcp.scp_data, buf, count);
662673 if (scpdata_len % 8) {
663674 padding = 8 - (scpdata_len % 8);
664
- memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len,
675
+ memset(reipl_block_fcp->fcp.scp_data + scpdata_len,
665676 0, padding);
666677 scpdata_len += padding;
667678 }
668679
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;
680
+ reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
681
+ reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN + scpdata_len;
682
+ reipl_block_fcp->fcp.scp_data_len = scpdata_len;
672683
673684 return count;
674685 }
....@@ -682,20 +693,20 @@
682693 };
683694
684695 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
685
- reipl_block_fcp->ipl_info.fcp.wwpn);
696
+ reipl_block_fcp->fcp.wwpn);
686697 DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
687
- reipl_block_fcp->ipl_info.fcp.lun);
698
+ reipl_block_fcp->fcp.lun);
688699 DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
689
- reipl_block_fcp->ipl_info.fcp.bootprog);
700
+ reipl_block_fcp->fcp.bootprog);
690701 DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
691
- reipl_block_fcp->ipl_info.fcp.br_lba);
702
+ reipl_block_fcp->fcp.br_lba);
692703 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
693
- reipl_block_fcp->ipl_info.fcp.devno);
704
+ reipl_block_fcp->fcp.devno);
694705
695706 static void reipl_get_ascii_loadparm(char *loadparm,
696707 struct ipl_parameter_block *ibp)
697708 {
698
- memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
709
+ memcpy(loadparm, ibp->common.loadparm, LOADPARM_LEN);
699710 EBCASC(loadparm, LOADPARM_LEN);
700711 loadparm[LOADPARM_LEN] = 0;
701712 strim(loadparm);
....@@ -730,11 +741,11 @@
730741 return -EINVAL;
731742 }
732743 /* initialize loadparm with blanks */
733
- memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
744
+ memset(ipb->common.loadparm, ' ', LOADPARM_LEN);
734745 /* 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;
746
+ memcpy(ipb->common.loadparm, buf, lp_len);
747
+ ASCEBC(ipb->common.loadparm, LOADPARM_LEN);
748
+ ipb->common.flags |= IPL_PB0_FLAG_LOADPARM;
738749 return len;
739750 }
740751
....@@ -756,6 +767,21 @@
756767 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
757768 reipl_fcp_loadparm_store);
758769
770
+static ssize_t reipl_fcp_clear_show(struct kobject *kobj,
771
+ struct kobj_attribute *attr, char *page)
772
+{
773
+ return sprintf(page, "%u\n", reipl_fcp_clear);
774
+}
775
+
776
+static ssize_t reipl_fcp_clear_store(struct kobject *kobj,
777
+ struct kobj_attribute *attr,
778
+ const char *buf, size_t len)
779
+{
780
+ if (strtobool(buf, &reipl_fcp_clear) < 0)
781
+ return -EINVAL;
782
+ return len;
783
+}
784
+
759785 static struct attribute *reipl_fcp_attrs[] = {
760786 &sys_reipl_fcp_device_attr.attr,
761787 &sys_reipl_fcp_wwpn_attr.attr,
....@@ -771,8 +797,116 @@
771797 .bin_attrs = reipl_fcp_bin_attrs,
772798 };
773799
800
+static struct kobj_attribute sys_reipl_fcp_clear_attr =
801
+ __ATTR(clear, 0644, reipl_fcp_clear_show, reipl_fcp_clear_store);
802
+
803
+/* NVME reipl device attributes */
804
+
805
+static ssize_t reipl_nvme_scpdata_read(struct file *filp, struct kobject *kobj,
806
+ struct bin_attribute *attr,
807
+ char *buf, loff_t off, size_t count)
808
+{
809
+ size_t size = reipl_block_nvme->nvme.scp_data_len;
810
+ void *scp_data = reipl_block_nvme->nvme.scp_data;
811
+
812
+ return memory_read_from_buffer(buf, count, &off, scp_data, size);
813
+}
814
+
815
+static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
816
+ struct bin_attribute *attr,
817
+ char *buf, loff_t off, size_t count)
818
+{
819
+ size_t scpdata_len = count;
820
+ size_t padding;
821
+
822
+ if (off)
823
+ return -EINVAL;
824
+
825
+ memcpy(reipl_block_nvme->nvme.scp_data, buf, count);
826
+ if (scpdata_len % 8) {
827
+ padding = 8 - (scpdata_len % 8);
828
+ memset(reipl_block_nvme->nvme.scp_data + scpdata_len,
829
+ 0, padding);
830
+ scpdata_len += padding;
831
+ }
832
+
833
+ reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
834
+ reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len;
835
+ reipl_block_nvme->nvme.scp_data_len = scpdata_len;
836
+
837
+ return count;
838
+}
839
+
840
+static struct bin_attribute sys_reipl_nvme_scp_data_attr =
841
+ __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read,
842
+ reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE);
843
+
844
+static struct bin_attribute *reipl_nvme_bin_attrs[] = {
845
+ &sys_reipl_nvme_scp_data_attr,
846
+ NULL,
847
+};
848
+
849
+DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n",
850
+ reipl_block_nvme->nvme.fid);
851
+DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n",
852
+ reipl_block_nvme->nvme.nsid);
853
+DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
854
+ reipl_block_nvme->nvme.bootprog);
855
+DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n",
856
+ reipl_block_nvme->nvme.br_lba);
857
+
858
+/* nvme wrapper */
859
+static ssize_t reipl_nvme_loadparm_show(struct kobject *kobj,
860
+ struct kobj_attribute *attr, char *page)
861
+{
862
+ return reipl_generic_loadparm_show(reipl_block_nvme, page);
863
+}
864
+
865
+static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj,
866
+ struct kobj_attribute *attr,
867
+ const char *buf, size_t len)
868
+{
869
+ return reipl_generic_loadparm_store(reipl_block_nvme, buf, len);
870
+}
871
+
872
+static struct kobj_attribute sys_reipl_nvme_loadparm_attr =
873
+ __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show,
874
+ reipl_nvme_loadparm_store);
875
+
876
+static struct attribute *reipl_nvme_attrs[] = {
877
+ &sys_reipl_nvme_fid_attr.attr,
878
+ &sys_reipl_nvme_nsid_attr.attr,
879
+ &sys_reipl_nvme_bootprog_attr.attr,
880
+ &sys_reipl_nvme_br_lba_attr.attr,
881
+ &sys_reipl_nvme_loadparm_attr.attr,
882
+ NULL,
883
+};
884
+
885
+static struct attribute_group reipl_nvme_attr_group = {
886
+ .attrs = reipl_nvme_attrs,
887
+ .bin_attrs = reipl_nvme_bin_attrs
888
+};
889
+
890
+static ssize_t reipl_nvme_clear_show(struct kobject *kobj,
891
+ struct kobj_attribute *attr, char *page)
892
+{
893
+ return sprintf(page, "%u\n", reipl_nvme_clear);
894
+}
895
+
896
+static ssize_t reipl_nvme_clear_store(struct kobject *kobj,
897
+ struct kobj_attribute *attr,
898
+ const char *buf, size_t len)
899
+{
900
+ if (strtobool(buf, &reipl_nvme_clear) < 0)
901
+ return -EINVAL;
902
+ return len;
903
+}
904
+
905
+static struct kobj_attribute sys_reipl_nvme_clear_attr =
906
+ __ATTR(clear, 0644, reipl_nvme_clear_show, reipl_nvme_clear_store);
907
+
774908 /* CCW reipl device attributes */
775
-DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ipl_info.ccw);
909
+DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw);
776910
777911 /* NSS wrapper */
778912 static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
....@@ -806,16 +940,36 @@
806940 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
807941 reipl_ccw_loadparm_store);
808942
943
+static ssize_t reipl_ccw_clear_show(struct kobject *kobj,
944
+ struct kobj_attribute *attr, char *page)
945
+{
946
+ return sprintf(page, "%u\n", reipl_ccw_clear);
947
+}
948
+
949
+static ssize_t reipl_ccw_clear_store(struct kobject *kobj,
950
+ struct kobj_attribute *attr,
951
+ const char *buf, size_t len)
952
+{
953
+ if (strtobool(buf, &reipl_ccw_clear) < 0)
954
+ return -EINVAL;
955
+ return len;
956
+}
957
+
958
+static struct kobj_attribute sys_reipl_ccw_clear_attr =
959
+ __ATTR(clear, 0644, reipl_ccw_clear_show, reipl_ccw_clear_store);
960
+
809961 static struct attribute *reipl_ccw_attrs_vm[] = {
810962 &sys_reipl_ccw_device_attr.attr,
811963 &sys_reipl_ccw_loadparm_attr.attr,
812964 &sys_reipl_ccw_vmparm_attr.attr,
965
+ &sys_reipl_ccw_clear_attr.attr,
813966 NULL,
814967 };
815968
816969 static struct attribute *reipl_ccw_attrs_lpar[] = {
817970 &sys_reipl_ccw_device_attr.attr,
818971 &sys_reipl_ccw_loadparm_attr.attr,
972
+ &sys_reipl_ccw_clear_attr.attr,
819973 NULL,
820974 };
821975
....@@ -834,7 +988,7 @@
834988 static void reipl_get_ascii_nss_name(char *dst,
835989 struct ipl_parameter_block *ipb)
836990 {
837
- memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
991
+ memcpy(dst, ipb->ccw.nss_name, NSS_NAME_SIZE);
838992 EBCASC(dst, NSS_NAME_SIZE);
839993 dst[NSS_NAME_SIZE] = 0;
840994 }
....@@ -862,16 +1016,14 @@
8621016 if (nss_len > NSS_NAME_SIZE)
8631017 return -EINVAL;
8641018
865
- memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
1019
+ memset(reipl_block_nss->ccw.nss_name, 0x40, NSS_NAME_SIZE);
8661020 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);
1021
+ reipl_block_nss->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_NSS;
1022
+ memcpy(reipl_block_nss->ccw.nss_name, buf, nss_len);
1023
+ ASCEBC(reipl_block_nss->ccw.nss_name, nss_len);
1024
+ EBC_TOUPPER(reipl_block_nss->ccw.nss_name, nss_len);
8721025 } else {
873
- reipl_block_nss->ipl_info.ccw.vm_flags &=
874
- ~DIAG308_VM_FLAGS_NSS_VALID;
1026
+ reipl_block_nss->ccw.vm_flags &= ~IPL_PB0_CCW_VM_FLAG_NSS;
8751027 }
8761028
8771029 return len;
....@@ -917,6 +1069,9 @@
9171069 case IPL_TYPE_FCP:
9181070 reipl_block_actual = reipl_block_fcp;
9191071 break;
1072
+ case IPL_TYPE_NVME:
1073
+ reipl_block_actual = reipl_block_nvme;
1074
+ break;
9201075 case IPL_TYPE_NSS:
9211076 reipl_block_actual = reipl_block_nss;
9221077 break;
....@@ -943,6 +1098,8 @@
9431098 rc = reipl_set_type(IPL_TYPE_CCW);
9441099 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
9451100 rc = reipl_set_type(IPL_TYPE_FCP);
1101
+ else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0)
1102
+ rc = reipl_set_type(IPL_TYPE_NVME);
9461103 else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
9471104 rc = reipl_set_type(IPL_TYPE_NSS);
9481105 return (rc != 0) ? rc : len;
....@@ -953,17 +1110,31 @@
9531110
9541111 static struct kset *reipl_kset;
9551112 static struct kset *reipl_fcp_kset;
1113
+static struct kset *reipl_nvme_kset;
9561114
9571115 static void __reipl_run(void *unused)
9581116 {
9591117 switch (reipl_type) {
9601118 case IPL_TYPE_CCW:
9611119 diag308(DIAG308_SET, reipl_block_ccw);
962
- diag308(DIAG308_LOAD_CLEAR, NULL);
1120
+ if (reipl_ccw_clear)
1121
+ diag308(DIAG308_LOAD_CLEAR, NULL);
1122
+ else
1123
+ diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
9631124 break;
9641125 case IPL_TYPE_FCP:
9651126 diag308(DIAG308_SET, reipl_block_fcp);
966
- diag308(DIAG308_LOAD_CLEAR, NULL);
1127
+ if (reipl_fcp_clear)
1128
+ diag308(DIAG308_LOAD_CLEAR, NULL);
1129
+ else
1130
+ diag308(DIAG308_LOAD_NORMAL, NULL);
1131
+ break;
1132
+ case IPL_TYPE_NVME:
1133
+ diag308(DIAG308_SET, reipl_block_nvme);
1134
+ if (reipl_nvme_clear)
1135
+ diag308(DIAG308_LOAD_CLEAR, NULL);
1136
+ else
1137
+ diag308(DIAG308_LOAD_NORMAL, NULL);
9671138 break;
9681139 case IPL_TYPE_NSS:
9691140 diag308(DIAG308_SET, reipl_block_nss);
....@@ -973,9 +1144,10 @@
9731144 diag308(DIAG308_LOAD_CLEAR, NULL);
9741145 break;
9751146 case IPL_TYPE_FCP_DUMP:
1147
+ case IPL_TYPE_NVME_DUMP:
9761148 break;
9771149 }
978
- disabled_wait((unsigned long) __builtin_return_address(0));
1150
+ disabled_wait();
9791151 }
9801152
9811153 static void reipl_run(struct shutdown_trigger *trigger)
....@@ -985,10 +1157,10 @@
9851157
9861158 static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
9871159 {
988
- ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
1160
+ ipb->hdr.len = IPL_BP_CCW_LEN;
9891161 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;
1162
+ ipb->pb0_hdr.len = IPL_BP0_CCW_LEN;
1163
+ ipb->pb0_hdr.pbt = IPL_PBT_CCW;
9921164 }
9931165
9941166 static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
....@@ -996,21 +1168,20 @@
9961168 /* LOADPARM */
9971169 /* check if read scp info worked and set loadparm */
9981170 if (sclp_ipl_info.is_valid)
999
- memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
1171
+ memcpy(ipb->ccw.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
10001172 else
10011173 /* 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;
1174
+ memset(ipb->ccw.loadparm, 0x40, LOADPARM_LEN);
1175
+ ipb->ccw.flags = IPL_PB0_FLAG_LOADPARM;
10041176
10051177 /* VM PARM */
10061178 if (MACHINE_IS_VM && ipl_block_valid &&
1007
- (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
1179
+ (ipl_block.ccw.vm_flags & IPL_PB0_CCW_VM_FLAG_VP)) {
10081180
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);
1181
+ ipb->ccw.vm_flags |= IPL_PB0_CCW_VM_FLAG_VP;
1182
+ ipb->ccw.vm_parm_len = ipl_block.ccw.vm_parm_len;
1183
+ memcpy(ipb->ccw.vm_parm,
1184
+ ipl_block.ccw.vm_parm, DIAG308_VMPARM_SIZE);
10141185 }
10151186 }
10161187
....@@ -1050,8 +1221,8 @@
10501221
10511222 reipl_block_ccw_init(reipl_block_ccw);
10521223 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;
1224
+ reipl_block_ccw->ccw.ssid = ipl_block.ccw.ssid;
1225
+ reipl_block_ccw->ccw.devno = ipl_block.ccw.devno;
10551226 reipl_block_ccw_fill_parms(reipl_block_ccw);
10561227 }
10571228
....@@ -1076,10 +1247,16 @@
10761247 }
10771248
10781249 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;
1250
+ if (rc)
1251
+ goto out1;
1252
+
1253
+ if (test_facility(141)) {
1254
+ rc = sysfs_create_file(&reipl_fcp_kset->kobj,
1255
+ &sys_reipl_fcp_clear_attr.attr);
1256
+ if (rc)
1257
+ goto out2;
1258
+ } else {
1259
+ reipl_fcp_clear = true;
10831260 }
10841261
10851262 if (ipl_info.type == IPL_TYPE_FCP) {
....@@ -1089,17 +1266,80 @@
10891266 * is invalid in the SCSI IPL parameter block, so take it
10901267 * always from sclp_ipl_info.
10911268 */
1092
- memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
1269
+ memcpy(reipl_block_fcp->fcp.loadparm, sclp_ipl_info.loadparm,
10931270 LOADPARM_LEN);
10941271 } else {
1095
- reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1272
+ reipl_block_fcp->hdr.len = IPL_BP_FCP_LEN;
10961273 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;
1274
+ reipl_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
1275
+ reipl_block_fcp->fcp.pbt = IPL_PBT_FCP;
1276
+ reipl_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_IPL;
11001277 }
11011278 reipl_capabilities |= IPL_TYPE_FCP;
11021279 return 0;
1280
+
1281
+out2:
1282
+ sysfs_remove_group(&reipl_fcp_kset->kobj, &reipl_fcp_attr_group);
1283
+out1:
1284
+ kset_unregister(reipl_fcp_kset);
1285
+ free_page((unsigned long) reipl_block_fcp);
1286
+ return rc;
1287
+}
1288
+
1289
+static int __init reipl_nvme_init(void)
1290
+{
1291
+ int rc;
1292
+
1293
+ reipl_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
1294
+ if (!reipl_block_nvme)
1295
+ return -ENOMEM;
1296
+
1297
+ /* sysfs: create kset for mixing attr group and bin attrs */
1298
+ reipl_nvme_kset = kset_create_and_add(IPL_NVME_STR, NULL,
1299
+ &reipl_kset->kobj);
1300
+ if (!reipl_nvme_kset) {
1301
+ free_page((unsigned long) reipl_block_nvme);
1302
+ return -ENOMEM;
1303
+ }
1304
+
1305
+ rc = sysfs_create_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
1306
+ if (rc)
1307
+ goto out1;
1308
+
1309
+ if (test_facility(141)) {
1310
+ rc = sysfs_create_file(&reipl_nvme_kset->kobj,
1311
+ &sys_reipl_nvme_clear_attr.attr);
1312
+ if (rc)
1313
+ goto out2;
1314
+ } else {
1315
+ reipl_nvme_clear = true;
1316
+ }
1317
+
1318
+ if (ipl_info.type == IPL_TYPE_NVME) {
1319
+ memcpy(reipl_block_nvme, &ipl_block, sizeof(ipl_block));
1320
+ /*
1321
+ * Fix loadparm: There are systems where the (SCSI) LOADPARM
1322
+ * is invalid in the IPL parameter block, so take it
1323
+ * always from sclp_ipl_info.
1324
+ */
1325
+ memcpy(reipl_block_nvme->nvme.loadparm, sclp_ipl_info.loadparm,
1326
+ LOADPARM_LEN);
1327
+ } else {
1328
+ reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN;
1329
+ reipl_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
1330
+ reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN;
1331
+ reipl_block_nvme->nvme.pbt = IPL_PBT_NVME;
1332
+ reipl_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_IPL;
1333
+ }
1334
+ reipl_capabilities |= IPL_TYPE_NVME;
1335
+ return 0;
1336
+
1337
+out2:
1338
+ sysfs_remove_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
1339
+out1:
1340
+ kset_unregister(reipl_nvme_kset);
1341
+ free_page((unsigned long) reipl_block_nvme);
1342
+ return rc;
11031343 }
11041344
11051345 static int __init reipl_type_init(void)
....@@ -1114,10 +1354,13 @@
11141354 /*
11151355 * If we have an OS info reipl block, this will be used
11161356 */
1117
- if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_FCP) {
1357
+ if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) {
11181358 memcpy(reipl_block_fcp, reipl_block, size);
11191359 reipl_type = IPL_TYPE_FCP;
1120
- } else if (reipl_block->hdr.pbt == DIAG308_IPL_TYPE_CCW) {
1360
+ } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_NVME) {
1361
+ memcpy(reipl_block_nvme, reipl_block, size);
1362
+ reipl_type = IPL_TYPE_NVME;
1363
+ } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
11211364 memcpy(reipl_block_ccw, reipl_block, size);
11221365 reipl_type = IPL_TYPE_CCW;
11231366 }
....@@ -1143,6 +1386,9 @@
11431386 rc = reipl_fcp_init();
11441387 if (rc)
11451388 return rc;
1389
+ rc = reipl_nvme_init();
1390
+ if (rc)
1391
+ return rc;
11461392 rc = reipl_nss_init();
11471393 if (rc)
11481394 return rc;
....@@ -1162,15 +1408,15 @@
11621408 /* FCP dump device attributes */
11631409
11641410 DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
1165
- dump_block_fcp->ipl_info.fcp.wwpn);
1411
+ dump_block_fcp->fcp.wwpn);
11661412 DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
1167
- dump_block_fcp->ipl_info.fcp.lun);
1413
+ dump_block_fcp->fcp.lun);
11681414 DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
1169
- dump_block_fcp->ipl_info.fcp.bootprog);
1415
+ dump_block_fcp->fcp.bootprog);
11701416 DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n",
1171
- dump_block_fcp->ipl_info.fcp.br_lba);
1417
+ dump_block_fcp->fcp.br_lba);
11721418 DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
1173
- dump_block_fcp->ipl_info.fcp.devno);
1419
+ dump_block_fcp->fcp.devno);
11741420
11751421 static struct attribute *dump_fcp_attrs[] = {
11761422 &sys_dump_fcp_device_attr.attr,
....@@ -1186,8 +1432,31 @@
11861432 .attrs = dump_fcp_attrs,
11871433 };
11881434
1435
+/* NVME dump device attributes */
1436
+DEFINE_IPL_ATTR_RW(dump_nvme, fid, "0x%08llx\n", "%llx\n",
1437
+ dump_block_nvme->nvme.fid);
1438
+DEFINE_IPL_ATTR_RW(dump_nvme, nsid, "0x%08llx\n", "%llx\n",
1439
+ dump_block_nvme->nvme.nsid);
1440
+DEFINE_IPL_ATTR_RW(dump_nvme, bootprog, "%lld\n", "%llx\n",
1441
+ dump_block_nvme->nvme.bootprog);
1442
+DEFINE_IPL_ATTR_RW(dump_nvme, br_lba, "%lld\n", "%llx\n",
1443
+ dump_block_nvme->nvme.br_lba);
1444
+
1445
+static struct attribute *dump_nvme_attrs[] = {
1446
+ &sys_dump_nvme_fid_attr.attr,
1447
+ &sys_dump_nvme_nsid_attr.attr,
1448
+ &sys_dump_nvme_bootprog_attr.attr,
1449
+ &sys_dump_nvme_br_lba_attr.attr,
1450
+ NULL,
1451
+};
1452
+
1453
+static struct attribute_group dump_nvme_attr_group = {
1454
+ .name = IPL_NVME_STR,
1455
+ .attrs = dump_nvme_attrs,
1456
+};
1457
+
11891458 /* CCW dump device attributes */
1190
-DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ipl_info.ccw);
1459
+DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ccw);
11911460
11921461 static struct attribute *dump_ccw_attrs[] = {
11931462 &sys_dump_ccw_device_attr.attr,
....@@ -1227,6 +1496,8 @@
12271496 rc = dump_set_type(DUMP_TYPE_CCW);
12281497 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
12291498 rc = dump_set_type(DUMP_TYPE_FCP);
1499
+ else if (strncmp(buf, DUMP_NVME_STR, strlen(DUMP_NVME_STR)) == 0)
1500
+ rc = dump_set_type(DUMP_TYPE_NVME);
12301501 return (rc != 0) ? rc : len;
12311502 }
12321503
....@@ -1254,6 +1525,9 @@
12541525 case DUMP_TYPE_FCP:
12551526 diag308_dump(dump_block_fcp);
12561527 break;
1528
+ case DUMP_TYPE_NVME:
1529
+ diag308_dump(dump_block_nvme);
1530
+ break;
12571531 default:
12581532 break;
12591533 }
....@@ -1279,10 +1553,10 @@
12791553 free_page((unsigned long)dump_block_ccw);
12801554 return rc;
12811555 }
1282
- dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
1556
+ dump_block_ccw->hdr.len = IPL_BP_CCW_LEN;
12831557 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;
1558
+ dump_block_ccw->ccw.len = IPL_BP0_CCW_LEN;
1559
+ dump_block_ccw->ccw.pbt = IPL_PBT_CCW;
12861560 dump_capabilities |= DUMP_TYPE_CCW;
12871561 return 0;
12881562 }
....@@ -1301,12 +1575,35 @@
13011575 free_page((unsigned long)dump_block_fcp);
13021576 return rc;
13031577 }
1304
- dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1578
+ dump_block_fcp->hdr.len = IPL_BP_FCP_LEN;
13051579 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;
1580
+ dump_block_fcp->fcp.len = IPL_BP0_FCP_LEN;
1581
+ dump_block_fcp->fcp.pbt = IPL_PBT_FCP;
1582
+ dump_block_fcp->fcp.opt = IPL_PB0_FCP_OPT_DUMP;
13091583 dump_capabilities |= DUMP_TYPE_FCP;
1584
+ return 0;
1585
+}
1586
+
1587
+static int __init dump_nvme_init(void)
1588
+{
1589
+ int rc;
1590
+
1591
+ if (!sclp_ipl_info.has_dump)
1592
+ return 0; /* LDIPL DUMP is not installed */
1593
+ dump_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
1594
+ if (!dump_block_nvme)
1595
+ return -ENOMEM;
1596
+ rc = sysfs_create_group(&dump_kset->kobj, &dump_nvme_attr_group);
1597
+ if (rc) {
1598
+ free_page((unsigned long)dump_block_nvme);
1599
+ return rc;
1600
+ }
1601
+ dump_block_nvme->hdr.len = IPL_BP_NVME_LEN;
1602
+ dump_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
1603
+ dump_block_nvme->fcp.len = IPL_BP0_NVME_LEN;
1604
+ dump_block_nvme->fcp.pbt = IPL_PBT_NVME;
1605
+ dump_block_nvme->fcp.opt = IPL_PB0_NVME_OPT_DUMP;
1606
+ dump_capabilities |= DUMP_TYPE_NVME;
13101607 return 0;
13111608 }
13121609
....@@ -1326,6 +1623,9 @@
13261623 if (rc)
13271624 return rc;
13281625 rc = dump_fcp_init();
1626
+ if (rc)
1627
+ return rc;
1628
+ rc = dump_nvme_init();
13291629 if (rc)
13301630 return rc;
13311631 dump_set_type(DUMP_TYPE_NONE);
....@@ -1429,7 +1729,7 @@
14291729 {
14301730 if (strcmp(trigger->name, ON_PANIC_STR) == 0 ||
14311731 strcmp(trigger->name, ON_RESTART_STR) == 0)
1432
- disabled_wait((unsigned long) __builtin_return_address(0));
1732
+ disabled_wait();
14331733 smp_stop_cpu();
14341734 }
14351735
....@@ -1664,7 +1964,7 @@
16641964 * READ SCP info provides the correct value.
16651965 */
16661966 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);
1967
+ memcpy(sclp_ipl_info.loadparm, ipl_block.ccw.loadparm, LOADPARM_LEN);
16681968 shutdown_actions_init();
16691969 shutdown_triggers_init();
16701970 return 0;
....@@ -1749,15 +2049,20 @@
17492049 ipl_info.type = get_ipl_type();
17502050 switch (ipl_info.type) {
17512051 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;
2052
+ ipl_info.data.ccw.dev_id.ssid = ipl_block.ccw.ssid;
2053
+ ipl_info.data.ccw.dev_id.devno = ipl_block.ccw.devno;
17542054 break;
17552055 case IPL_TYPE_FCP:
17562056 case IPL_TYPE_FCP_DUMP:
17572057 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;
2058
+ ipl_info.data.fcp.dev_id.devno = ipl_block.fcp.devno;
2059
+ ipl_info.data.fcp.wwpn = ipl_block.fcp.wwpn;
2060
+ ipl_info.data.fcp.lun = ipl_block.fcp.lun;
2061
+ break;
2062
+ case IPL_TYPE_NVME:
2063
+ case IPL_TYPE_NVME_DUMP:
2064
+ ipl_info.data.nvme.fid = ipl_block.nvme.fid;
2065
+ ipl_info.data.nvme.nsid = ipl_block.nvme.nsid;
17612066 break;
17622067 case IPL_TYPE_NSS:
17632068 case IPL_TYPE_UNKNOWN:
....@@ -1767,15 +2072,6 @@
17672072 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
17682073 }
17692074
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
-
17792075 void s390_reset_system(void)
17802076 {
17812077 /* Disable prefixing */
....@@ -1783,5 +2079,140 @@
17832079
17842080 /* Disable lowcore protection */
17852081 __ctl_clear_bit(0, 28);
1786
- diag308_reset();
2082
+ diag_dma_ops.diag308_reset();
17872083 }
2084
+
2085
+#ifdef CONFIG_KEXEC_FILE
2086
+
2087
+int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf,
2088
+ unsigned char flags, unsigned short cert)
2089
+{
2090
+ struct ipl_report_component *comp;
2091
+
2092
+ comp = vzalloc(sizeof(*comp));
2093
+ if (!comp)
2094
+ return -ENOMEM;
2095
+ list_add_tail(&comp->list, &report->components);
2096
+
2097
+ comp->entry.addr = kbuf->mem;
2098
+ comp->entry.len = kbuf->memsz;
2099
+ comp->entry.flags = flags;
2100
+ comp->entry.certificate_index = cert;
2101
+
2102
+ report->size += sizeof(comp->entry);
2103
+
2104
+ return 0;
2105
+}
2106
+
2107
+int ipl_report_add_certificate(struct ipl_report *report, void *key,
2108
+ unsigned long addr, unsigned long len)
2109
+{
2110
+ struct ipl_report_certificate *cert;
2111
+
2112
+ cert = vzalloc(sizeof(*cert));
2113
+ if (!cert)
2114
+ return -ENOMEM;
2115
+ list_add_tail(&cert->list, &report->certificates);
2116
+
2117
+ cert->entry.addr = addr;
2118
+ cert->entry.len = len;
2119
+ cert->key = key;
2120
+
2121
+ report->size += sizeof(cert->entry);
2122
+ report->size += cert->entry.len;
2123
+
2124
+ return 0;
2125
+}
2126
+
2127
+struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib)
2128
+{
2129
+ struct ipl_report *report;
2130
+
2131
+ report = vzalloc(sizeof(*report));
2132
+ if (!report)
2133
+ return ERR_PTR(-ENOMEM);
2134
+
2135
+ report->ipib = ipib;
2136
+ INIT_LIST_HEAD(&report->components);
2137
+ INIT_LIST_HEAD(&report->certificates);
2138
+
2139
+ report->size = ALIGN(ipib->hdr.len, 8);
2140
+ report->size += sizeof(struct ipl_rl_hdr);
2141
+ report->size += sizeof(struct ipl_rb_components);
2142
+ report->size += sizeof(struct ipl_rb_certificates);
2143
+
2144
+ return report;
2145
+}
2146
+
2147
+void *ipl_report_finish(struct ipl_report *report)
2148
+{
2149
+ struct ipl_report_certificate *cert;
2150
+ struct ipl_report_component *comp;
2151
+ struct ipl_rb_certificates *certs;
2152
+ struct ipl_parameter_block *ipib;
2153
+ struct ipl_rb_components *comps;
2154
+ struct ipl_rl_hdr *rl_hdr;
2155
+ void *buf, *ptr;
2156
+
2157
+ buf = vzalloc(report->size);
2158
+ if (!buf)
2159
+ goto out;
2160
+ ptr = buf;
2161
+
2162
+ memcpy(ptr, report->ipib, report->ipib->hdr.len);
2163
+ ipib = ptr;
2164
+ if (ipl_secure_flag)
2165
+ ipib->hdr.flags |= IPL_PL_FLAG_SIPL;
2166
+ ipib->hdr.flags |= IPL_PL_FLAG_IPLSR;
2167
+ ptr += report->ipib->hdr.len;
2168
+ ptr = PTR_ALIGN(ptr, 8);
2169
+
2170
+ rl_hdr = ptr;
2171
+ ptr += sizeof(*rl_hdr);
2172
+
2173
+ comps = ptr;
2174
+ comps->rbt = IPL_RBT_COMPONENTS;
2175
+ ptr += sizeof(*comps);
2176
+ list_for_each_entry(comp, &report->components, list) {
2177
+ memcpy(ptr, &comp->entry, sizeof(comp->entry));
2178
+ ptr += sizeof(comp->entry);
2179
+ }
2180
+ comps->len = ptr - (void *)comps;
2181
+
2182
+ certs = ptr;
2183
+ certs->rbt = IPL_RBT_CERTIFICATES;
2184
+ ptr += sizeof(*certs);
2185
+ list_for_each_entry(cert, &report->certificates, list) {
2186
+ memcpy(ptr, &cert->entry, sizeof(cert->entry));
2187
+ ptr += sizeof(cert->entry);
2188
+ }
2189
+ certs->len = ptr - (void *)certs;
2190
+ rl_hdr->len = ptr - (void *)rl_hdr;
2191
+
2192
+ list_for_each_entry(cert, &report->certificates, list) {
2193
+ memcpy(ptr, cert->key, cert->entry.len);
2194
+ ptr += cert->entry.len;
2195
+ }
2196
+
2197
+ BUG_ON(ptr > buf + report->size);
2198
+out:
2199
+ return buf;
2200
+}
2201
+
2202
+int ipl_report_free(struct ipl_report *report)
2203
+{
2204
+ struct ipl_report_component *comp, *ncomp;
2205
+ struct ipl_report_certificate *cert, *ncert;
2206
+
2207
+ list_for_each_entry_safe(comp, ncomp, &report->components, list)
2208
+ vfree(comp);
2209
+
2210
+ list_for_each_entry_safe(cert, ncert, &report->certificates, list)
2211
+ vfree(cert);
2212
+
2213
+ vfree(report);
2214
+
2215
+ return 0;
2216
+}
2217
+
2218
+#endif