aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/early.c80
-rw-r--r--arch/s390/kernel/ipl.c444
-rw-r--r--arch/s390/kernel/setup.c17
3 files changed, 458 insertions, 83 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index b2226e41f067..e22473993dc9 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -14,6 +14,7 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/pfn.h> 15#include <linux/pfn.h>
16#include <linux/uaccess.h> 16#include <linux/uaccess.h>
17#include <asm/ebcdic.h>
17#include <asm/ipl.h> 18#include <asm/ipl.h>
18#include <asm/lowcore.h> 19#include <asm/lowcore.h>
19#include <asm/processor.h> 20#include <asm/processor.h>
@@ -26,12 +27,40 @@
26/* 27/*
27 * Create a Kernel NSS if the SAVESYS= parameter is defined 28 * Create a Kernel NSS if the SAVESYS= parameter is defined
28 */ 29 */
29#define DEFSYS_CMD_SIZE 96 30#define DEFSYS_CMD_SIZE 128
30#define SAVESYS_CMD_SIZE 32 31#define SAVESYS_CMD_SIZE 32
31 32
32char kernel_nss_name[NSS_NAME_SIZE + 1]; 33char kernel_nss_name[NSS_NAME_SIZE + 1];
33 34
35static void __init setup_boot_command_line(void);
36
37
34#ifdef CONFIG_SHARED_KERNEL 38#ifdef CONFIG_SHARED_KERNEL
39int __init savesys_ipl_nss(char *cmd, const int cmdlen);
40
41asm(
42 " .section .init.text,\"ax\",@progbits\n"
43 " .align 4\n"
44 " .type savesys_ipl_nss, @function\n"
45 "savesys_ipl_nss:\n"
46#ifdef CONFIG_64BIT
47 " stmg 6,15,48(15)\n"
48 " lgr 14,3\n"
49 " sam31\n"
50 " diag 2,14,0x8\n"
51 " sam64\n"
52 " lgr 2,14\n"
53 " lmg 6,15,48(15)\n"
54#else
55 " stm 6,15,24(15)\n"
56 " lr 14,3\n"
57 " diag 2,14,0x8\n"
58 " lr 2,14\n"
59 " lm 6,15,24(15)\n"
60#endif
61 " br 14\n"
62 " .size savesys_ipl_nss, .-savesys_ipl_nss\n");
63
35static noinline __init void create_kernel_nss(void) 64static noinline __init void create_kernel_nss(void)
36{ 65{
37 unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; 66 unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
@@ -39,6 +68,7 @@ static noinline __init void create_kernel_nss(void)
39 unsigned int sinitrd_pfn, einitrd_pfn; 68 unsigned int sinitrd_pfn, einitrd_pfn;
40#endif 69#endif
41 int response; 70 int response;
71 size_t len;
42 char *savesys_ptr; 72 char *savesys_ptr;
43 char upper_command_line[COMMAND_LINE_SIZE]; 73 char upper_command_line[COMMAND_LINE_SIZE];
44 char defsys_cmd[DEFSYS_CMD_SIZE]; 74 char defsys_cmd[DEFSYS_CMD_SIZE];
@@ -49,8 +79,8 @@ static noinline __init void create_kernel_nss(void)
49 return; 79 return;
50 80
51 /* Convert COMMAND_LINE to upper case */ 81 /* Convert COMMAND_LINE to upper case */
52 for (i = 0; i < strlen(COMMAND_LINE); i++) 82 for (i = 0; i < strlen(boot_command_line); i++)
53 upper_command_line[i] = toupper(COMMAND_LINE[i]); 83 upper_command_line[i] = toupper(boot_command_line[i]);
54 84
55 savesys_ptr = strstr(upper_command_line, "SAVESYS="); 85 savesys_ptr = strstr(upper_command_line, "SAVESYS=");
56 86
@@ -83,7 +113,8 @@ static noinline __init void create_kernel_nss(void)
83 } 113 }
84#endif 114#endif
85 115
86 sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size); 116 sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13",
117 defsys_cmd, min_size);
87 sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", 118 sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
88 kernel_nss_name, kernel_nss_name); 119 kernel_nss_name, kernel_nss_name);
89 120
@@ -94,13 +125,24 @@ static noinline __init void create_kernel_nss(void)
94 return; 125 return;
95 } 126 }
96 127
97 __cpcmd(savesys_cmd, NULL, 0, &response); 128 len = strlen(savesys_cmd);
129 ASCEBC(savesys_cmd, len);
130 response = savesys_ipl_nss(savesys_cmd, len);
98 131
99 if (response != strlen(savesys_cmd)) { 132 /* On success: response is equal to the command size,
133 * max SAVESYS_CMD_SIZE
134 * On error: response contains the numeric portion of cp error message.
135 * for SAVESYS it will be >= 263
136 */
137 if (response > SAVESYS_CMD_SIZE) {
100 kernel_nss_name[0] = '\0'; 138 kernel_nss_name[0] = '\0';
101 return; 139 return;
102 } 140 }
103 141
142 /* re-setup boot command line with new ipl vm parms */
143 ipl_update_parameters();
144 setup_boot_command_line();
145
104 ipl_flags = IPL_NSS_VALID; 146 ipl_flags = IPL_NSS_VALID;
105} 147}
106 148
@@ -397,6 +439,26 @@ static __init void rescue_initrd(void)
397#endif 439#endif
398} 440}
399 441
442/* Set up boot command line */
443static void __init setup_boot_command_line(void)
444{
445 char *parm = NULL;
446
447 /* copy arch command line */
448 strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
449 boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
450
451 /* append IPL PARM data to the boot command line */
452 if (MACHINE_IS_VM) {
453 parm = boot_command_line + strlen(boot_command_line);
454 *parm++ = ' ';
455 get_ipl_vmparm(parm);
456 if (parm[0] == '=')
457 memmove(boot_command_line, parm + 1, strlen(parm));
458 }
459}
460
461
400/* 462/*
401 * Save ipl parameters, clear bss memory, initialize storage keys 463 * Save ipl parameters, clear bss memory, initialize storage keys
402 * and create a kernel NSS at startup if the SAVESYS= parm is defined 464 * and create a kernel NSS at startup if the SAVESYS= parm is defined
@@ -411,10 +473,12 @@ void __init startup_init(void)
411 init_kernel_storage_key(); 473 init_kernel_storage_key();
412 lockdep_init(); 474 lockdep_init();
413 lockdep_off(); 475 lockdep_off();
414 detect_machine_type();
415 create_kernel_nss();
416 sort_main_extable(); 476 sort_main_extable();
417 setup_lowcore_early(); 477 setup_lowcore_early();
478 detect_machine_type();
479 ipl_update_parameters();
480 setup_boot_command_line();
481 create_kernel_nss();
418 detect_mvpg(); 482 detect_mvpg();
419 detect_ieee(); 483 detect_ieee();
420 detect_csp(); 484 detect_csp();
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 532542447d66..9f6dfd306abb 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -22,6 +22,7 @@
22#include <asm/ebcdic.h> 22#include <asm/ebcdic.h>
23#include <asm/reset.h> 23#include <asm/reset.h>
24#include <asm/sclp.h> 24#include <asm/sclp.h>
25#include <asm/setup.h>
25 26
26#define IPL_PARM_BLOCK_VERSION 0 27#define IPL_PARM_BLOCK_VERSION 0
27 28
@@ -121,6 +122,7 @@ enum ipl_method {
121 REIPL_METHOD_FCP_RO_VM, 122 REIPL_METHOD_FCP_RO_VM,
122 REIPL_METHOD_FCP_DUMP, 123 REIPL_METHOD_FCP_DUMP,
123 REIPL_METHOD_NSS, 124 REIPL_METHOD_NSS,
125 REIPL_METHOD_NSS_DIAG,
124 REIPL_METHOD_DEFAULT, 126 REIPL_METHOD_DEFAULT,
125}; 127};
126 128
@@ -134,14 +136,15 @@ enum dump_method {
134 136
135static int diag308_set_works = 0; 137static int diag308_set_works = 0;
136 138
139static struct ipl_parameter_block ipl_block;
140
137static int reipl_capabilities = IPL_TYPE_UNKNOWN; 141static int reipl_capabilities = IPL_TYPE_UNKNOWN;
138 142
139static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; 143static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
140static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; 144static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
141static struct ipl_parameter_block *reipl_block_fcp; 145static struct ipl_parameter_block *reipl_block_fcp;
142static struct ipl_parameter_block *reipl_block_ccw; 146static struct ipl_parameter_block *reipl_block_ccw;
143 147static struct ipl_parameter_block *reipl_block_nss;
144static char reipl_nss_name[NSS_NAME_SIZE + 1];
145 148
146static int dump_capabilities = DUMP_TYPE_NONE; 149static int dump_capabilities = DUMP_TYPE_NONE;
147static enum dump_type dump_type = DUMP_TYPE_NONE; 150static enum dump_type dump_type = DUMP_TYPE_NONE;
@@ -263,6 +266,56 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
263 266
264static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); 267static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
265 268
269/* VM IPL PARM routines */
270static void reipl_get_ascii_vmparm(char *dest,
271 const struct ipl_parameter_block *ipb)
272{
273 int i;
274 int len = 0;
275 char has_lowercase = 0;
276
277 if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
278 (ipb->ipl_info.ccw.vm_parm_len > 0)) {
279
280 len = ipb->ipl_info.ccw.vm_parm_len;
281 memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
282 /* If at least one character is lowercase, we assume mixed
283 * case; otherwise we convert everything to lowercase.
284 */
285 for (i = 0; i < len; i++)
286 if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
287 (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
288 (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
289 has_lowercase = 1;
290 break;
291 }
292 if (!has_lowercase)
293 EBC_TOLOWER(dest, len);
294 EBCASC(dest, len);
295 }
296 dest[len] = 0;
297}
298
299void get_ipl_vmparm(char *dest)
300{
301 if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
302 reipl_get_ascii_vmparm(dest, &ipl_block);
303 else
304 dest[0] = 0;
305}
306
307static ssize_t ipl_vm_parm_show(struct kobject *kobj,
308 struct kobj_attribute *attr, char *page)
309{
310 char parm[DIAG308_VMPARM_SIZE + 1] = {};
311
312 get_ipl_vmparm(parm);
313 return sprintf(page, "%s\n", parm);
314}
315
316static struct kobj_attribute sys_ipl_vm_parm_attr =
317 __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
318
266static ssize_t sys_ipl_device_show(struct kobject *kobj, 319static ssize_t sys_ipl_device_show(struct kobject *kobj,
267 struct kobj_attribute *attr, char *page) 320 struct kobj_attribute *attr, char *page)
268{ 321{
@@ -370,15 +423,27 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
370static struct kobj_attribute sys_ipl_ccw_loadparm_attr = 423static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
371 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); 424 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
372 425
373static struct attribute *ipl_ccw_attrs[] = { 426static struct attribute *ipl_ccw_attrs_vm[] = {
427 &sys_ipl_type_attr.attr,
428 &sys_ipl_device_attr.attr,
429 &sys_ipl_ccw_loadparm_attr.attr,
430 &sys_ipl_vm_parm_attr.attr,
431 NULL,
432};
433
434static struct attribute *ipl_ccw_attrs_lpar[] = {
374 &sys_ipl_type_attr.attr, 435 &sys_ipl_type_attr.attr,
375 &sys_ipl_device_attr.attr, 436 &sys_ipl_device_attr.attr,
376 &sys_ipl_ccw_loadparm_attr.attr, 437 &sys_ipl_ccw_loadparm_attr.attr,
377 NULL, 438 NULL,
378}; 439};
379 440
380static struct attribute_group ipl_ccw_attr_group = { 441static struct attribute_group ipl_ccw_attr_group_vm = {
381 .attrs = ipl_ccw_attrs, 442 .attrs = ipl_ccw_attrs_vm,
443};
444
445static struct attribute_group ipl_ccw_attr_group_lpar = {
446 .attrs = ipl_ccw_attrs_lpar
382}; 447};
383 448
384/* NSS ipl device attributes */ 449/* NSS ipl device attributes */
@@ -388,6 +453,8 @@ DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
388static struct attribute *ipl_nss_attrs[] = { 453static struct attribute *ipl_nss_attrs[] = {
389 &sys_ipl_type_attr.attr, 454 &sys_ipl_type_attr.attr,
390 &sys_ipl_nss_name_attr.attr, 455 &sys_ipl_nss_name_attr.attr,
456 &sys_ipl_ccw_loadparm_attr.attr,
457 &sys_ipl_vm_parm_attr.attr,
391 NULL, 458 NULL,
392}; 459};
393 460
@@ -450,7 +517,12 @@ static int __init ipl_init(void)
450 } 517 }
451 switch (ipl_info.type) { 518 switch (ipl_info.type) {
452 case IPL_TYPE_CCW: 519 case IPL_TYPE_CCW:
453 rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group); 520 if (MACHINE_IS_VM)
521 rc = sysfs_create_group(&ipl_kset->kobj,
522 &ipl_ccw_attr_group_vm);
523 else
524 rc = sysfs_create_group(&ipl_kset->kobj,
525 &ipl_ccw_attr_group_lpar);
454 break; 526 break;
455 case IPL_TYPE_FCP: 527 case IPL_TYPE_FCP:
456 case IPL_TYPE_FCP_DUMP: 528 case IPL_TYPE_FCP_DUMP:
@@ -481,6 +553,83 @@ static struct shutdown_action __refdata ipl_action = {
481 * reipl shutdown action: Reboot Linux on shutdown. 553 * reipl shutdown action: Reboot Linux on shutdown.
482 */ 554 */
483 555
556/* VM IPL PARM attributes */
557static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
558 char *page)
559{
560 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
561
562 reipl_get_ascii_vmparm(vmparm, ipb);
563 return sprintf(page, "%s\n", vmparm);
564}
565
566static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
567 size_t vmparm_max,
568 const char *buf, size_t len)
569{
570 int i, ip_len;
571
572 /* ignore trailing newline */
573 ip_len = len;
574 if ((len > 0) && (buf[len - 1] == '\n'))
575 ip_len--;
576
577 if (ip_len > vmparm_max)
578 return -EINVAL;
579
580 /* parm is used to store kernel options, check for common chars */
581 for (i = 0; i < ip_len; i++)
582 if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
583 return -EINVAL;
584
585 memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
586 ipb->ipl_info.ccw.vm_parm_len = ip_len;
587 if (ip_len > 0) {
588 ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
589 memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
590 ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
591 } else {
592 ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
593 }
594
595 return len;
596}
597
598/* NSS wrapper */
599static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
600 struct kobj_attribute *attr, char *page)
601{
602 return reipl_generic_vmparm_show(reipl_block_nss, page);
603}
604
605static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
606 struct kobj_attribute *attr,
607 const char *buf, size_t len)
608{
609 return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
610}
611
612/* CCW wrapper */
613static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
614 struct kobj_attribute *attr, char *page)
615{
616 return reipl_generic_vmparm_show(reipl_block_ccw, page);
617}
618
619static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
620 struct kobj_attribute *attr,
621 const char *buf, size_t len)
622{
623 return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
624}
625
626static struct kobj_attribute sys_reipl_nss_vmparm_attr =
627 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
628 reipl_nss_vmparm_store);
629static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
630 __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
631 reipl_ccw_vmparm_store);
632
484/* FCP reipl device attributes */ 633/* FCP reipl device attributes */
485 634
486DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n", 635DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
@@ -513,27 +662,26 @@ static struct attribute_group reipl_fcp_attr_group = {
513DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", 662DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
514 reipl_block_ccw->ipl_info.ccw.devno); 663 reipl_block_ccw->ipl_info.ccw.devno);
515 664
516static void reipl_get_ascii_loadparm(char *loadparm) 665static void reipl_get_ascii_loadparm(char *loadparm,
666 struct ipl_parameter_block *ibp)
517{ 667{
518 memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param, 668 memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
519 LOADPARM_LEN);
520 EBCASC(loadparm, LOADPARM_LEN); 669 EBCASC(loadparm, LOADPARM_LEN);
521 loadparm[LOADPARM_LEN] = 0; 670 loadparm[LOADPARM_LEN] = 0;
522 strstrip(loadparm); 671 strstrip(loadparm);
523} 672}
524 673
525static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj, 674static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
526 struct kobj_attribute *attr, char *page) 675 char *page)
527{ 676{
528 char buf[LOADPARM_LEN + 1]; 677 char buf[LOADPARM_LEN + 1];
529 678
530 reipl_get_ascii_loadparm(buf); 679 reipl_get_ascii_loadparm(buf, ipb);
531 return sprintf(page, "%s\n", buf); 680 return sprintf(page, "%s\n", buf);
532} 681}
533 682
534static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj, 683static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
535 struct kobj_attribute *attr, 684 const char *buf, size_t len)
536 const char *buf, size_t len)
537{ 685{
538 int i, lp_len; 686 int i, lp_len;
539 687
@@ -552,35 +700,128 @@ static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
552 return -EINVAL; 700 return -EINVAL;
553 } 701 }
554 /* initialize loadparm with blanks */ 702 /* initialize loadparm with blanks */
555 memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN); 703 memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
556 /* copy and convert to ebcdic */ 704 /* copy and convert to ebcdic */
557 memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len); 705 memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
558 ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN); 706 ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
559 return len; 707 return len;
560} 708}
561 709
710/* NSS wrapper */
711static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
712 struct kobj_attribute *attr, char *page)
713{
714 return reipl_generic_loadparm_show(reipl_block_nss, page);
715}
716
717static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
718 struct kobj_attribute *attr,
719 const char *buf, size_t len)
720{
721 return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
722}
723
724/* CCW wrapper */
725static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
726 struct kobj_attribute *attr, char *page)
727{
728 return reipl_generic_loadparm_show(reipl_block_ccw, page);
729}
730
731static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
732 struct kobj_attribute *attr,
733 const char *buf, size_t len)
734{
735 return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
736}
737
562static struct kobj_attribute sys_reipl_ccw_loadparm_attr = 738static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
563 __ATTR(loadparm, 0644, reipl_ccw_loadparm_show, 739 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
564 reipl_ccw_loadparm_store); 740 reipl_ccw_loadparm_store);
741
742static struct attribute *reipl_ccw_attrs_vm[] = {
743 &sys_reipl_ccw_device_attr.attr,
744 &sys_reipl_ccw_loadparm_attr.attr,
745 &sys_reipl_ccw_vmparm_attr.attr,
746 NULL,
747};
565 748
566static struct attribute *reipl_ccw_attrs[] = { 749static struct attribute *reipl_ccw_attrs_lpar[] = {
567 &sys_reipl_ccw_device_attr.attr, 750 &sys_reipl_ccw_device_attr.attr,
568 &sys_reipl_ccw_loadparm_attr.attr, 751 &sys_reipl_ccw_loadparm_attr.attr,
569 NULL, 752 NULL,
570}; 753};
571 754
572static struct attribute_group reipl_ccw_attr_group = { 755static struct attribute_group reipl_ccw_attr_group_vm = {
573 .name = IPL_CCW_STR, 756 .name = IPL_CCW_STR,
574 .attrs = reipl_ccw_attrs, 757 .attrs = reipl_ccw_attrs_vm,
758};
759
760static struct attribute_group reipl_ccw_attr_group_lpar = {
761 .name = IPL_CCW_STR,
762 .attrs = reipl_ccw_attrs_lpar,
575}; 763};
576 764
577 765
578/* NSS reipl device attributes */ 766/* NSS reipl device attributes */
767static void reipl_get_ascii_nss_name(char *dst,
768 struct ipl_parameter_block *ipb)
769{
770 memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
771 EBCASC(dst, NSS_NAME_SIZE);
772 dst[NSS_NAME_SIZE] = 0;
773}
774
775static ssize_t reipl_nss_name_show(struct kobject *kobj,
776 struct kobj_attribute *attr, char *page)
777{
778 char nss_name[NSS_NAME_SIZE + 1] = {};
779
780 reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
781 return sprintf(page, "%s\n", nss_name);
782}
783
784static ssize_t reipl_nss_name_store(struct kobject *kobj,
785 struct kobj_attribute *attr,
786 const char *buf, size_t len)
787{
788 int nss_len;
789
790 /* ignore trailing newline */
791 nss_len = len;
792 if ((len > 0) && (buf[len - 1] == '\n'))
793 nss_len--;
579 794
580DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name); 795 if (nss_len > NSS_NAME_SIZE)
796 return -EINVAL;
797
798 memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
799 if (nss_len > 0) {
800 reipl_block_nss->ipl_info.ccw.vm_flags |=
801 DIAG308_VM_FLAGS_NSS_VALID;
802 memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
803 ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
804 EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
805 } else {
806 reipl_block_nss->ipl_info.ccw.vm_flags &=
807 ~DIAG308_VM_FLAGS_NSS_VALID;
808 }
809
810 return len;
811}
812
813static struct kobj_attribute sys_reipl_nss_name_attr =
814 __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
815 reipl_nss_name_store);
816
817static struct kobj_attribute sys_reipl_nss_loadparm_attr =
818 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
819 reipl_nss_loadparm_store);
581 820
582static struct attribute *reipl_nss_attrs[] = { 821static struct attribute *reipl_nss_attrs[] = {
583 &sys_reipl_nss_name_attr.attr, 822 &sys_reipl_nss_name_attr.attr,
823 &sys_reipl_nss_loadparm_attr.attr,
824 &sys_reipl_nss_vmparm_attr.attr,
584 NULL, 825 NULL,
585}; 826};
586 827
@@ -617,7 +858,10 @@ static int reipl_set_type(enum ipl_type type)
617 reipl_method = REIPL_METHOD_FCP_DUMP; 858 reipl_method = REIPL_METHOD_FCP_DUMP;
618 break; 859 break;
619 case IPL_TYPE_NSS: 860 case IPL_TYPE_NSS:
620 reipl_method = REIPL_METHOD_NSS; 861 if (diag308_set_works)
862 reipl_method = REIPL_METHOD_NSS_DIAG;
863 else
864 reipl_method = REIPL_METHOD_NSS;
621 break; 865 break;
622 case IPL_TYPE_UNKNOWN: 866 case IPL_TYPE_UNKNOWN:
623 reipl_method = REIPL_METHOD_DEFAULT; 867 reipl_method = REIPL_METHOD_DEFAULT;
@@ -655,11 +899,38 @@ static struct kobj_attribute reipl_type_attr =
655 899
656static struct kset *reipl_kset; 900static struct kset *reipl_kset;
657 901
902static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
903 const enum ipl_method m)
904{
905 char loadparm[LOADPARM_LEN + 1] = {};
906 char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
907 char nss_name[NSS_NAME_SIZE + 1] = {};
908 size_t pos = 0;
909
910 reipl_get_ascii_loadparm(loadparm, ipb);
911 reipl_get_ascii_nss_name(nss_name, ipb);
912 reipl_get_ascii_vmparm(vmparm, ipb);
913
914 switch (m) {
915 case REIPL_METHOD_CCW_VM:
916 pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno);
917 break;
918 case REIPL_METHOD_NSS:
919 pos = sprintf(dst, "IPL %s", nss_name);
920 break;
921 default:
922 break;
923 }
924 if (strlen(loadparm) > 0)
925 pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm);
926 if (strlen(vmparm) > 0)
927 sprintf(dst + pos, " PARM %s", vmparm);
928}
929
658static void reipl_run(struct shutdown_trigger *trigger) 930static void reipl_run(struct shutdown_trigger *trigger)
659{ 931{
660 struct ccw_dev_id devid; 932 struct ccw_dev_id devid;
661 static char buf[100]; 933 static char buf[128];
662 char loadparm[LOADPARM_LEN + 1];
663 934
664 switch (reipl_method) { 935 switch (reipl_method) {
665 case REIPL_METHOD_CCW_CIO: 936 case REIPL_METHOD_CCW_CIO:
@@ -668,13 +939,7 @@ static void reipl_run(struct shutdown_trigger *trigger)
668 reipl_ccw_dev(&devid); 939 reipl_ccw_dev(&devid);
669 break; 940 break;
670 case REIPL_METHOD_CCW_VM: 941 case REIPL_METHOD_CCW_VM:
671 reipl_get_ascii_loadparm(loadparm); 942 get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM);
672 if (strlen(loadparm) == 0)
673 sprintf(buf, "IPL %X CLEAR",
674 reipl_block_ccw->ipl_info.ccw.devno);
675 else
676 sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
677 reipl_block_ccw->ipl_info.ccw.devno, loadparm);
678 __cpcmd(buf, NULL, 0, NULL); 943 __cpcmd(buf, NULL, 0, NULL);
679 break; 944 break;
680 case REIPL_METHOD_CCW_DIAG: 945 case REIPL_METHOD_CCW_DIAG:
@@ -691,8 +956,12 @@ static void reipl_run(struct shutdown_trigger *trigger)
691 case REIPL_METHOD_FCP_RO_VM: 956 case REIPL_METHOD_FCP_RO_VM:
692 __cpcmd("IPL", NULL, 0, NULL); 957 __cpcmd("IPL", NULL, 0, NULL);
693 break; 958 break;
959 case REIPL_METHOD_NSS_DIAG:
960 diag308(DIAG308_SET, reipl_block_nss);
961 diag308(DIAG308_IPL, NULL);
962 break;
694 case REIPL_METHOD_NSS: 963 case REIPL_METHOD_NSS:
695 sprintf(buf, "IPL %s", reipl_nss_name); 964 get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS);
696 __cpcmd(buf, NULL, 0, NULL); 965 __cpcmd(buf, NULL, 0, NULL);
697 break; 966 break;
698 case REIPL_METHOD_DEFAULT: 967 case REIPL_METHOD_DEFAULT:
@@ -707,16 +976,36 @@ static void reipl_run(struct shutdown_trigger *trigger)
707 disabled_wait((unsigned long) __builtin_return_address(0)); 976 disabled_wait((unsigned long) __builtin_return_address(0));
708} 977}
709 978
710static void __init reipl_probe(void) 979static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
711{ 980{
712 void *buffer; 981 ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
982 ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
983 ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
984 ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
985}
713 986
714 buffer = (void *) get_zeroed_page(GFP_KERNEL); 987static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
715 if (!buffer) 988{
716 return; 989 /* LOADPARM */
717 if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK) 990 /* check if read scp info worked and set loadparm */
718 diag308_set_works = 1; 991 if (sclp_ipl_info.is_valid)
719 free_page((unsigned long)buffer); 992 memcpy(ipb->ipl_info.ccw.load_parm,
993 &sclp_ipl_info.loadparm, LOADPARM_LEN);
994 else
995 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
996 memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
997 ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
998
999 /* VM PARM */
1000 if (MACHINE_IS_VM && diag308_set_works &&
1001 (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
1002
1003 ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
1004 ipb->ipl_info.ccw.vm_parm_len =
1005 ipl_block.ipl_info.ccw.vm_parm_len;
1006 memcpy(ipb->ipl_info.ccw.vm_parm,
1007 ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
1008 }
720} 1009}
721 1010
722static int __init reipl_nss_init(void) 1011static int __init reipl_nss_init(void)
@@ -725,10 +1014,31 @@ static int __init reipl_nss_init(void)
725 1014
726 if (!MACHINE_IS_VM) 1015 if (!MACHINE_IS_VM)
727 return 0; 1016 return 0;
1017
1018 reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
1019 if (!reipl_block_nss)
1020 return -ENOMEM;
1021
1022 if (!diag308_set_works)
1023 sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO;
1024
728 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group); 1025 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
729 if (rc) 1026 if (rc)
730 return rc; 1027 return rc;
731 strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); 1028
1029 reipl_block_ccw_init(reipl_block_nss);
1030 if (ipl_info.type == IPL_TYPE_NSS) {
1031 memset(reipl_block_nss->ipl_info.ccw.nss_name,
1032 ' ', NSS_NAME_SIZE);
1033 memcpy(reipl_block_nss->ipl_info.ccw.nss_name,
1034 kernel_nss_name, strlen(kernel_nss_name));
1035 ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
1036 reipl_block_nss->ipl_info.ccw.vm_flags |=
1037 DIAG308_VM_FLAGS_NSS_VALID;
1038
1039 reipl_block_ccw_fill_parms(reipl_block_nss);
1040 }
1041
732 reipl_capabilities |= IPL_TYPE_NSS; 1042 reipl_capabilities |= IPL_TYPE_NSS;
733 return 0; 1043 return 0;
734} 1044}
@@ -740,28 +1050,27 @@ static int __init reipl_ccw_init(void)
740 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); 1050 reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
741 if (!reipl_block_ccw) 1051 if (!reipl_block_ccw)
742 return -ENOMEM; 1052 return -ENOMEM;
743 rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group); 1053
744 if (rc) { 1054 if (MACHINE_IS_VM) {
745 free_page((unsigned long)reipl_block_ccw); 1055 if (!diag308_set_works)
746 return rc; 1056 sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO;
1057 rc = sysfs_create_group(&reipl_kset->kobj,
1058 &reipl_ccw_attr_group_vm);
1059 } else {
1060 if(!diag308_set_works)
1061 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
1062 rc = sysfs_create_group(&reipl_kset->kobj,
1063 &reipl_ccw_attr_group_lpar);
747 } 1064 }
748 reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN; 1065 if (rc)
749 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; 1066 return rc;
750 reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; 1067
751 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; 1068 reipl_block_ccw_init(reipl_block_ccw);
752 reipl_block_ccw->hdr.flags = DIAG308_FLAGS_LP_VALID; 1069 if (ipl_info.type == IPL_TYPE_CCW) {
753 /* check if read scp info worked and set loadparm */
754 if (sclp_ipl_info.is_valid)
755 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
756 &sclp_ipl_info.loadparm, LOADPARM_LEN);
757 else
758 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
759 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
760 LOADPARM_LEN);
761 if (!MACHINE_IS_VM && !diag308_set_works)
762 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
763 if (ipl_info.type == IPL_TYPE_CCW)
764 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; 1070 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
1071 reipl_block_ccw_fill_parms(reipl_block_ccw);
1072 }
1073
765 reipl_capabilities |= IPL_TYPE_CCW; 1074 reipl_capabilities |= IPL_TYPE_CCW;
766 return 0; 1075 return 0;
767} 1076}
@@ -1298,7 +1607,6 @@ static void __init shutdown_actions_init(void)
1298 1607
1299static int __init s390_ipl_init(void) 1608static int __init s390_ipl_init(void)
1300{ 1609{
1301 reipl_probe();
1302 sclp_get_ipl_info(&sclp_ipl_info); 1610 sclp_get_ipl_info(&sclp_ipl_info);
1303 shutdown_actions_init(); 1611 shutdown_actions_init();
1304 shutdown_triggers_init(); 1612 shutdown_triggers_init();
@@ -1405,6 +1713,12 @@ void __init setup_ipl(void)
1405 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb); 1713 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
1406} 1714}
1407 1715
1716void __init ipl_update_parameters(void)
1717{
1718 if (diag308(DIAG308_STORE, &ipl_block) == DIAG308_RC_OK)
1719 diag308_set_works = 1;
1720}
1721
1408void __init ipl_save_parameters(void) 1722void __init ipl_save_parameters(void)
1409{ 1723{
1410 struct cio_iplinfo iplinfo; 1724 struct cio_iplinfo iplinfo;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b91caadf974d..e3b4cdbae34e 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -221,18 +221,17 @@ static void __init conmode_default(void)
221#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) 221#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
222static void __init setup_zfcpdump(unsigned int console_devno) 222static void __init setup_zfcpdump(unsigned int console_devno)
223{ 223{
224 static char str[64]; 224 static char str[41];
225 225
226 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 226 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
227 return; 227 return;
228 if (console_devno != -1) 228 if (console_devno != -1)
229 sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x", 229 sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
230 ipl_info.data.fcp.dev_id.devno, console_devno); 230 ipl_info.data.fcp.dev_id.devno, console_devno);
231 else 231 else
232 sprintf(str, "cio_ignore=all,!0.0.%04x", 232 sprintf(str, " cio_ignore=all,!0.0.%04x",
233 ipl_info.data.fcp.dev_id.devno); 233 ipl_info.data.fcp.dev_id.devno);
234 strcat(COMMAND_LINE, " "); 234 strcat(boot_command_line, str);
235 strcat(COMMAND_LINE, str);
236 console_loglevel = 2; 235 console_loglevel = 2;
237} 236}
238#else 237#else
@@ -778,11 +777,9 @@ setup_arch(char **cmdline_p)
778 printk("We are running native (64 bit mode)\n"); 777 printk("We are running native (64 bit mode)\n");
779#endif /* CONFIG_64BIT */ 778#endif /* CONFIG_64BIT */
780 779
781 /* Save unparsed command line copy for /proc/cmdline */ 780 /* Have one command line that is parsed and saved in /proc/cmdline */
782 strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); 781 /* boot_command_line has been already set up in early.c */
783 782 *cmdline_p = boot_command_line;
784 *cmdline_p = COMMAND_LINE;
785 *(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0';
786 783
787 ROOT_DEV = Root_RAM0; 784 ROOT_DEV = Root_RAM0;
788 785