aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/Makefile3
-rw-r--r--arch/s390/defconfig1
-rw-r--r--arch/s390/kernel/head64.S72
-rw-r--r--arch/s390/kernel/ipl.c232
-rw-r--r--arch/s390/kernel/setup.c38
-rw-r--r--arch/s390/kernel/smp.c62
7 files changed, 330 insertions, 86 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 0f9517bc8e70..e6ec418093e5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -519,6 +519,14 @@ config KEXEC
519 current kernel, and to start another kernel. It is like a reboot 519 current kernel, and to start another kernel. It is like a reboot
520 but is independent of hardware/microcode support. 520 but is independent of hardware/microcode support.
521 521
522config ZFCPDUMP
523 tristate "zfcpdump support"
524 select SMP
525 default n
526 help
527 Select this option if you want to build an zfcpdump enabled kernel.
528 Refer to "Documentation/s390/zfcpdump.txt" for more details on this.
529
522endmenu 530endmenu
523 531
524source "net/Kconfig" 532source "net/Kconfig"
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index ece5adc05606..68441e0e74b6 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -105,6 +105,9 @@ install: vmlinux
105image: vmlinux 105image: vmlinux
106 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ 106 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
107 107
108zfcpdump:
109 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
110
108archclean: 111archclean:
109 $(Q)$(MAKE) $(clean)=$(boot) 112 $(Q)$(MAKE) $(clean)=$(boot)
110 113
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 80046d9e2a3b..0e4da8a7d826 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -167,6 +167,7 @@ CONFIG_NO_IDLE_HZ=y
167CONFIG_NO_IDLE_HZ_INIT=y 167CONFIG_NO_IDLE_HZ_INIT=y
168CONFIG_S390_HYPFS_FS=y 168CONFIG_S390_HYPFS_FS=y
169CONFIG_KEXEC=y 169CONFIG_KEXEC=y
170# CONFIG_ZFCPDUMP is not set
170 171
171# 172#
172# Networking 173# Networking
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 37010709fe68..a87b1976d409 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -39,7 +39,69 @@ startup_continue:
39 basr %r13,0 # get base 39 basr %r13,0 # get base
40.LPG1: sll %r13,1 # remove high order bit 40.LPG1: sll %r13,1 # remove high order bit
41 srl %r13,1 41 srl %r13,1
42 lhi %r1,1 # mode 1 = esame 42
43#ifdef CONFIG_ZFCPDUMP
44
45 # check if we have been ipled using zfcp dump:
46
47 tm 0xb9,0x01 # test if subchannel is enabled
48 jno .nodump # subchannel disabled
49 l %r1,0xb8
50 la %r5,.Lipl_schib-.LPG1(%r13)
51 stsch 0(%r5) # get schib of subchannel
52 jne .nodump # schib not available
53 tm 5(%r5),0x01 # devno valid?
54 jno .nodump
55 tm 4(%r5),0x80 # qdio capable device?
56 jno .nodump
57 l %r2,20(%r0) # address of ipl parameter block
58 lhi %r3,0
59 ic %r3,0x148(%r2) # get opt field
60 chi %r3,0x20 # load with dump?
61 jne .nodump
62
63 # store all prefix registers in case of load with dump:
64
65 la %r7,0 # base register for 0 page
66 la %r8,0 # first cpu
67 l %r11,.Lpref_arr_ptr-.LPG1(%r13) # address of prefix array
68 ahi %r11,4 # skip boot cpu
69 lr %r12,%r11
70 ahi %r12,(CONFIG_NR_CPUS*4) # end of prefix array
71 stap .Lcurrent_cpu+2-.LPG1(%r13) # store current cpu addr
721:
73 cl %r8,.Lcurrent_cpu-.LPG1(%r13) # is ipl cpu ?
74 je 4f # if yes get next cpu
752:
76 lr %r9,%r7
77 sigp %r9,%r8,0x9 # stop & store status of cpu
78 brc 8,3f # accepted
79 brc 4,4f # status stored: next cpu
80 brc 2,2b # busy: try again
81 brc 1,4f # not op: next cpu
823:
83 mvc 0(4,%r11),264(%r7) # copy prefix register to prefix array
84 ahi %r11,4 # next element in prefix array
85 clr %r11,%r12
86 je 5f # no more space in prefix array
874:
88 ahi %r8,1 # next cpu (r8 += 1)
89 cl %r8,.Llast_cpu-.LPG1(%r13) # is last possible cpu ?
90 jl 1b # jump if not last cpu
915:
92 lhi %r1,2 # mode 2 = esame (dump)
93 j 6f
94 .align 4
95.Lipl_schib:
96 .rept 13
97 .long 0
98 .endr
99.nodump:
100 lhi %r1,1 # mode 1 = esame (normal ipl)
1016:
102#else
103 lhi %r1,1 # mode 1 = esame (normal ipl)
104#endif /* CONFIG_ZFCPDUMP */
43 mvi __LC_AR_MODE_ID,1 # set esame flag 105 mvi __LC_AR_MODE_ID,1 # set esame flag
44 slr %r0,%r0 # set cpuid to zero 106 slr %r0,%r0 # set cpuid to zero
45 sigp %r1,%r0,0x12 # switch to esame mode 107 sigp %r1,%r0,0x12 # switch to esame mode
@@ -149,6 +211,14 @@ startup_continue:
149.L4malign:.quad 0xffffffffffc00000 211.L4malign:.quad 0xffffffffffc00000
150.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 212.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
151.Lnop: .long 0x07000700 213.Lnop: .long 0x07000700
214#ifdef CONFIG_ZFCPDUMP
215.Lcurrent_cpu:
216 .long 0x0
217.Llast_cpu:
218 .long 0x0000ffff
219.Lpref_arr_ptr:
220 .long zfcpdump_prefix_array
221#endif /* CONFIG_ZFCPDUMP */
152.Lparmaddr: 222.Lparmaddr:
153 .quad PARMAREA 223 .quad PARMAREA
154 .align 64 224 .align 64
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index a83cf1fdd8f5..06833ac2b115 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -29,36 +29,21 @@
29#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm) 29#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
30#define SCCB_FLAG (s390_readinfo_sccb.flags) 30#define SCCB_FLAG (s390_readinfo_sccb.flags)
31 31
32enum ipl_type { 32#define IPL_UNKNOWN_STR "unknown"
33 IPL_TYPE_NONE = 1, 33#define IPL_CCW_STR "ccw"
34 IPL_TYPE_UNKNOWN = 2, 34#define IPL_FCP_STR "fcp"
35 IPL_TYPE_CCW = 4, 35#define IPL_FCP_DUMP_STR "fcp_dump"
36 IPL_TYPE_FCP = 8, 36#define IPL_NSS_STR "nss"
37 IPL_TYPE_NSS = 16,
38};
39
40#define IPL_NONE_STR "none"
41#define IPL_UNKNOWN_STR "unknown"
42#define IPL_CCW_STR "ccw"
43#define IPL_FCP_STR "fcp"
44#define IPL_NSS_STR "nss"
45
46/*
47 * Must be in data section since the bss section
48 * is not cleared when these are accessed.
49 */
50static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
51u32 ipl_flags __attribute__((__section__(".data"))) = 0;
52 37
53static char *ipl_type_str(enum ipl_type type) 38static char *ipl_type_str(enum ipl_type type)
54{ 39{
55 switch (type) { 40 switch (type) {
56 case IPL_TYPE_NONE:
57 return IPL_NONE_STR;
58 case IPL_TYPE_CCW: 41 case IPL_TYPE_CCW:
59 return IPL_CCW_STR; 42 return IPL_CCW_STR;
60 case IPL_TYPE_FCP: 43 case IPL_TYPE_FCP:
61 return IPL_FCP_STR; 44 return IPL_FCP_STR;
45 case IPL_TYPE_FCP_DUMP:
46 return IPL_FCP_DUMP_STR;
62 case IPL_TYPE_NSS: 47 case IPL_TYPE_NSS:
63 return IPL_NSS_STR; 48 return IPL_NSS_STR;
64 case IPL_TYPE_UNKNOWN: 49 case IPL_TYPE_UNKNOWN:
@@ -67,15 +52,55 @@ static char *ipl_type_str(enum ipl_type type)
67 } 52 }
68} 53}
69 54
55enum dump_type {
56 DUMP_TYPE_NONE = 1,
57 DUMP_TYPE_CCW = 2,
58 DUMP_TYPE_FCP = 4,
59};
60
61#define DUMP_NONE_STR "none"
62#define DUMP_CCW_STR "ccw"
63#define DUMP_FCP_STR "fcp"
64
65static char *dump_type_str(enum dump_type type)
66{
67 switch (type) {
68 case DUMP_TYPE_NONE:
69 return DUMP_NONE_STR;
70 case DUMP_TYPE_CCW:
71 return DUMP_CCW_STR;
72 case DUMP_TYPE_FCP:
73 return DUMP_FCP_STR;
74 default:
75 return NULL;
76 }
77}
78
79/*
80 * Must be in data section since the bss section
81 * is not cleared when these are accessed.
82 */
83static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
84u32 ipl_flags __attribute__((__section__(".data"))) = 0;
85
70enum ipl_method { 86enum ipl_method {
71 IPL_METHOD_NONE, 87 REIPL_METHOD_CCW_CIO,
72 IPL_METHOD_CCW_CIO, 88 REIPL_METHOD_CCW_DIAG,
73 IPL_METHOD_CCW_DIAG, 89 REIPL_METHOD_CCW_VM,
74 IPL_METHOD_CCW_VM, 90 REIPL_METHOD_FCP_RO_DIAG,
75 IPL_METHOD_FCP_RO_DIAG, 91 REIPL_METHOD_FCP_RW_DIAG,
76 IPL_METHOD_FCP_RW_DIAG, 92 REIPL_METHOD_FCP_RO_VM,
77 IPL_METHOD_FCP_RO_VM, 93 REIPL_METHOD_FCP_DUMP,
78 IPL_METHOD_NSS, 94 REIPL_METHOD_NSS,
95 REIPL_METHOD_DEFAULT,
96};
97
98enum dump_method {
99 DUMP_METHOD_NONE,
100 DUMP_METHOD_CCW_CIO,
101 DUMP_METHOD_CCW_DIAG,
102 DUMP_METHOD_CCW_VM,
103 DUMP_METHOD_FCP_DIAG,
79}; 104};
80 105
81enum shutdown_action { 106enum shutdown_action {
@@ -107,15 +132,15 @@ static int diag308_set_works = 0;
107static int reipl_capabilities = IPL_TYPE_UNKNOWN; 132static int reipl_capabilities = IPL_TYPE_UNKNOWN;
108 133
109static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; 134static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
110static enum ipl_method reipl_method = IPL_METHOD_NONE; 135static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
111static struct ipl_parameter_block *reipl_block_fcp; 136static struct ipl_parameter_block *reipl_block_fcp;
112static struct ipl_parameter_block *reipl_block_ccw; 137static struct ipl_parameter_block *reipl_block_ccw;
113 138
114static char reipl_nss_name[NSS_NAME_SIZE + 1]; 139static char reipl_nss_name[NSS_NAME_SIZE + 1];
115 140
116static int dump_capabilities = IPL_TYPE_NONE; 141static int dump_capabilities = DUMP_TYPE_NONE;
117static enum ipl_type dump_type = IPL_TYPE_NONE; 142static enum dump_type dump_type = DUMP_TYPE_NONE;
118static enum ipl_method dump_method = IPL_METHOD_NONE; 143static enum dump_method dump_method = DUMP_METHOD_NONE;
119static struct ipl_parameter_block *dump_block_fcp; 144static struct ipl_parameter_block *dump_block_fcp;
120static struct ipl_parameter_block *dump_block_ccw; 145static struct ipl_parameter_block *dump_block_ccw;
121 146
@@ -134,6 +159,7 @@ int diag308(unsigned long subcode, void *addr)
134 : "d" (subcode) : "cc", "memory"); 159 : "d" (subcode) : "cc", "memory");
135 return _rc; 160 return _rc;
136} 161}
162EXPORT_SYMBOL_GPL(diag308);
137 163
138/* SYSFS */ 164/* SYSFS */
139 165
@@ -197,7 +223,7 @@ static void make_attrs_ro(struct attribute **attrs)
197 * ipl section 223 * ipl section
198 */ 224 */
199 225
200static enum ipl_type ipl_get_type(void) 226static __init enum ipl_type get_ipl_type(void)
201{ 227{
202 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; 228 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
203 229
@@ -211,12 +237,44 @@ static enum ipl_type ipl_get_type(void)
211 return IPL_TYPE_UNKNOWN; 237 return IPL_TYPE_UNKNOWN;
212 if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP) 238 if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP)
213 return IPL_TYPE_UNKNOWN; 239 return IPL_TYPE_UNKNOWN;
240 if (ipl->ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP)
241 return IPL_TYPE_FCP_DUMP;
214 return IPL_TYPE_FCP; 242 return IPL_TYPE_FCP;
215} 243}
216 244
245void __init setup_ipl_info(void)
246{
247 ipl_info.type = get_ipl_type();
248 switch (ipl_info.type) {
249 case IPL_TYPE_CCW:
250 ipl_info.data.ccw.dev_id.devno = ipl_devno;
251 ipl_info.data.ccw.dev_id.ssid = 0;
252 break;
253 case IPL_TYPE_FCP:
254 case IPL_TYPE_FCP_DUMP:
255 ipl_info.data.fcp.dev_id.devno =
256 IPL_PARMBLOCK_START->ipl_info.fcp.devno;
257 ipl_info.data.fcp.dev_id.ssid = 0;
258 ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
259 ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
260 break;
261 case IPL_TYPE_NSS:
262 strncpy(ipl_info.data.nss.name, kernel_nss_name,
263 sizeof(ipl_info.data.nss.name));
264 break;
265 case IPL_TYPE_UNKNOWN:
266 default:
267 /* We have no info to copy */
268 break;
269 }
270}
271
272struct ipl_info ipl_info;
273EXPORT_SYMBOL_GPL(ipl_info);
274
217static ssize_t ipl_type_show(struct subsystem *subsys, char *page) 275static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
218{ 276{
219 return sprintf(page, "%s\n", ipl_type_str(ipl_get_type())); 277 return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
220} 278}
221 279
222static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); 280static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
@@ -225,10 +283,11 @@ static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
225{ 283{
226 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; 284 struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
227 285
228 switch (ipl_get_type()) { 286 switch (ipl_info.type) {
229 case IPL_TYPE_CCW: 287 case IPL_TYPE_CCW:
230 return sprintf(page, "0.0.%04x\n", ipl_devno); 288 return sprintf(page, "0.0.%04x\n", ipl_devno);
231 case IPL_TYPE_FCP: 289 case IPL_TYPE_FCP:
290 case IPL_TYPE_FCP_DUMP:
232 return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno); 291 return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
233 default: 292 default:
234 return 0; 293 return 0;
@@ -485,23 +544,29 @@ static int reipl_set_type(enum ipl_type type)
485 switch(type) { 544 switch(type) {
486 case IPL_TYPE_CCW: 545 case IPL_TYPE_CCW:
487 if (MACHINE_IS_VM) 546 if (MACHINE_IS_VM)
488 reipl_method = IPL_METHOD_CCW_VM; 547 reipl_method = REIPL_METHOD_CCW_VM;
489 else 548 else
490 reipl_method = IPL_METHOD_CCW_CIO; 549 reipl_method = REIPL_METHOD_CCW_CIO;
491 break; 550 break;
492 case IPL_TYPE_FCP: 551 case IPL_TYPE_FCP:
493 if (diag308_set_works) 552 if (diag308_set_works)
494 reipl_method = IPL_METHOD_FCP_RW_DIAG; 553 reipl_method = REIPL_METHOD_FCP_RW_DIAG;
495 else if (MACHINE_IS_VM) 554 else if (MACHINE_IS_VM)
496 reipl_method = IPL_METHOD_FCP_RO_VM; 555 reipl_method = REIPL_METHOD_FCP_RO_VM;
497 else 556 else
498 reipl_method = IPL_METHOD_FCP_RO_DIAG; 557 reipl_method = REIPL_METHOD_FCP_RO_DIAG;
558 break;
559 case IPL_TYPE_FCP_DUMP:
560 reipl_method = REIPL_METHOD_FCP_DUMP;
499 break; 561 break;
500 case IPL_TYPE_NSS: 562 case IPL_TYPE_NSS:
501 reipl_method = IPL_METHOD_NSS; 563 reipl_method = REIPL_METHOD_NSS;
564 break;
565 case IPL_TYPE_UNKNOWN:
566 reipl_method = REIPL_METHOD_DEFAULT;
502 break; 567 break;
503 default: 568 default:
504 reipl_method = IPL_METHOD_NONE; 569 BUG();
505 } 570 }
506 reipl_type = type; 571 reipl_type = type;
507 return 0; 572 return 0;
@@ -579,22 +644,22 @@ static struct attribute_group dump_ccw_attr_group = {
579 644
580/* dump type */ 645/* dump type */
581 646
582static int dump_set_type(enum ipl_type type) 647static int dump_set_type(enum dump_type type)
583{ 648{
584 if (!(dump_capabilities & type)) 649 if (!(dump_capabilities & type))
585 return -EINVAL; 650 return -EINVAL;
586 switch(type) { 651 switch(type) {
587 case IPL_TYPE_CCW: 652 case DUMP_TYPE_CCW:
588 if (MACHINE_IS_VM) 653 if (MACHINE_IS_VM)
589 dump_method = IPL_METHOD_CCW_VM; 654 dump_method = DUMP_METHOD_CCW_VM;
590 else 655 else
591 dump_method = IPL_METHOD_CCW_CIO; 656 dump_method = DUMP_METHOD_CCW_CIO;
592 break; 657 break;
593 case IPL_TYPE_FCP: 658 case DUMP_TYPE_FCP:
594 dump_method = IPL_METHOD_FCP_RW_DIAG; 659 dump_method = DUMP_METHOD_FCP_DIAG;
595 break; 660 break;
596 default: 661 default:
597 dump_method = IPL_METHOD_NONE; 662 dump_method = DUMP_METHOD_NONE;
598 } 663 }
599 dump_type = type; 664 dump_type = type;
600 return 0; 665 return 0;
@@ -602,7 +667,7 @@ static int dump_set_type(enum ipl_type type)
602 667
603static ssize_t dump_type_show(struct subsystem *subsys, char *page) 668static ssize_t dump_type_show(struct subsystem *subsys, char *page)
604{ 669{
605 return sprintf(page, "%s\n", ipl_type_str(dump_type)); 670 return sprintf(page, "%s\n", dump_type_str(dump_type));
606} 671}
607 672
608static ssize_t dump_type_store(struct subsystem *subsys, const char *buf, 673static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
@@ -610,12 +675,12 @@ static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
610{ 675{
611 int rc = -EINVAL; 676 int rc = -EINVAL;
612 677
613 if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0) 678 if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
614 rc = dump_set_type(IPL_TYPE_NONE); 679 rc = dump_set_type(DUMP_TYPE_NONE);
615 else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0) 680 else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
616 rc = dump_set_type(IPL_TYPE_CCW); 681 rc = dump_set_type(DUMP_TYPE_CCW);
617 else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) 682 else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
618 rc = dump_set_type(IPL_TYPE_FCP); 683 rc = dump_set_type(DUMP_TYPE_FCP);
619 return (rc != 0) ? rc : len; 684 return (rc != 0) ? rc : len;
620} 685}
621 686
@@ -664,14 +729,14 @@ void do_reipl(void)
664 char loadparm[LOADPARM_LEN + 1]; 729 char loadparm[LOADPARM_LEN + 1];
665 730
666 switch (reipl_method) { 731 switch (reipl_method) {
667 case IPL_METHOD_CCW_CIO: 732 case REIPL_METHOD_CCW_CIO:
668 devid.devno = reipl_block_ccw->ipl_info.ccw.devno; 733 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
669 if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno) 734 if (ipl_info.type == IPL_TYPE_CCW && devid.devno == ipl_devno)
670 diag308(DIAG308_IPL, NULL); 735 diag308(DIAG308_IPL, NULL);
671 devid.ssid = 0; 736 devid.ssid = 0;
672 reipl_ccw_dev(&devid); 737 reipl_ccw_dev(&devid);
673 break; 738 break;
674 case IPL_METHOD_CCW_VM: 739 case REIPL_METHOD_CCW_VM:
675 reipl_get_ascii_loadparm(loadparm); 740 reipl_get_ascii_loadparm(loadparm);
676 if (strlen(loadparm) == 0) 741 if (strlen(loadparm) == 0)
677 sprintf(buf, "IPL %X", 742 sprintf(buf, "IPL %X",
@@ -681,30 +746,32 @@ void do_reipl(void)
681 reipl_block_ccw->ipl_info.ccw.devno, loadparm); 746 reipl_block_ccw->ipl_info.ccw.devno, loadparm);
682 __cpcmd(buf, NULL, 0, NULL); 747 __cpcmd(buf, NULL, 0, NULL);
683 break; 748 break;
684 case IPL_METHOD_CCW_DIAG: 749 case REIPL_METHOD_CCW_DIAG:
685 diag308(DIAG308_SET, reipl_block_ccw); 750 diag308(DIAG308_SET, reipl_block_ccw);
686 diag308(DIAG308_IPL, NULL); 751 diag308(DIAG308_IPL, NULL);
687 break; 752 break;
688 case IPL_METHOD_FCP_RW_DIAG: 753 case REIPL_METHOD_FCP_RW_DIAG:
689 diag308(DIAG308_SET, reipl_block_fcp); 754 diag308(DIAG308_SET, reipl_block_fcp);
690 diag308(DIAG308_IPL, NULL); 755 diag308(DIAG308_IPL, NULL);
691 break; 756 break;
692 case IPL_METHOD_FCP_RO_DIAG: 757 case REIPL_METHOD_FCP_RO_DIAG:
693 diag308(DIAG308_IPL, NULL); 758 diag308(DIAG308_IPL, NULL);
694 break; 759 break;
695 case IPL_METHOD_FCP_RO_VM: 760 case REIPL_METHOD_FCP_RO_VM:
696 __cpcmd("IPL", NULL, 0, NULL); 761 __cpcmd("IPL", NULL, 0, NULL);
697 break; 762 break;
698 case IPL_METHOD_NSS: 763 case REIPL_METHOD_NSS:
699 sprintf(buf, "IPL %s", reipl_nss_name); 764 sprintf(buf, "IPL %s", reipl_nss_name);
700 __cpcmd(buf, NULL, 0, NULL); 765 __cpcmd(buf, NULL, 0, NULL);
701 break; 766 break;
702 case IPL_METHOD_NONE: 767 case REIPL_METHOD_DEFAULT:
703 default:
704 if (MACHINE_IS_VM) 768 if (MACHINE_IS_VM)
705 __cpcmd("IPL", NULL, 0, NULL); 769 __cpcmd("IPL", NULL, 0, NULL);
706 diag308(DIAG308_IPL, NULL); 770 diag308(DIAG308_IPL, NULL);
707 break; 771 break;
772 case REIPL_METHOD_FCP_DUMP:
773 default:
774 break;
708 } 775 }
709 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 776 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
710} 777}
@@ -715,28 +782,28 @@ static void do_dump(void)
715 static char buf[100]; 782 static char buf[100];
716 783
717 switch (dump_method) { 784 switch (dump_method) {
718 case IPL_METHOD_CCW_CIO: 785 case DUMP_METHOD_CCW_CIO:
719 smp_send_stop(); 786 smp_send_stop();
720 devid.devno = dump_block_ccw->ipl_info.ccw.devno; 787 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
721 devid.ssid = 0; 788 devid.ssid = 0;
722 reipl_ccw_dev(&devid); 789 reipl_ccw_dev(&devid);
723 break; 790 break;
724 case IPL_METHOD_CCW_VM: 791 case DUMP_METHOD_CCW_VM:
725 smp_send_stop(); 792 smp_send_stop();
726 sprintf(buf, "STORE STATUS"); 793 sprintf(buf, "STORE STATUS");
727 __cpcmd(buf, NULL, 0, NULL); 794 __cpcmd(buf, NULL, 0, NULL);
728 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); 795 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
729 __cpcmd(buf, NULL, 0, NULL); 796 __cpcmd(buf, NULL, 0, NULL);
730 break; 797 break;
731 case IPL_METHOD_CCW_DIAG: 798 case DUMP_METHOD_CCW_DIAG:
732 diag308(DIAG308_SET, dump_block_ccw); 799 diag308(DIAG308_SET, dump_block_ccw);
733 diag308(DIAG308_DUMP, NULL); 800 diag308(DIAG308_DUMP, NULL);
734 break; 801 break;
735 case IPL_METHOD_FCP_RW_DIAG: 802 case DUMP_METHOD_FCP_DIAG:
736 diag308(DIAG308_SET, dump_block_fcp); 803 diag308(DIAG308_SET, dump_block_fcp);
737 diag308(DIAG308_DUMP, NULL); 804 diag308(DIAG308_DUMP, NULL);
738 break; 805 break;
739 case IPL_METHOD_NONE: 806 case DUMP_METHOD_NONE:
740 default: 807 default:
741 return; 808 return;
742 } 809 }
@@ -777,12 +844,13 @@ static int __init ipl_init(void)
777 rc = firmware_register(&ipl_subsys); 844 rc = firmware_register(&ipl_subsys);
778 if (rc) 845 if (rc)
779 return rc; 846 return rc;
780 switch (ipl_get_type()) { 847 switch (ipl_info.type) {
781 case IPL_TYPE_CCW: 848 case IPL_TYPE_CCW:
782 rc = sysfs_create_group(&ipl_subsys.kset.kobj, 849 rc = sysfs_create_group(&ipl_subsys.kset.kobj,
783 &ipl_ccw_attr_group); 850 &ipl_ccw_attr_group);
784 break; 851 break;
785 case IPL_TYPE_FCP: 852 case IPL_TYPE_FCP:
853 case IPL_TYPE_FCP_DUMP:
786 rc = ipl_register_fcp_files(); 854 rc = ipl_register_fcp_files();
787 break; 855 break;
788 case IPL_TYPE_NSS: 856 case IPL_TYPE_NSS:
@@ -852,7 +920,7 @@ static int __init reipl_ccw_init(void)
852 /* FIXME: check for diag308_set_works when enabling diag ccw reipl */ 920 /* FIXME: check for diag308_set_works when enabling diag ccw reipl */
853 if (!MACHINE_IS_VM) 921 if (!MACHINE_IS_VM)
854 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO; 922 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
855 if (ipl_get_type() == IPL_TYPE_CCW) 923 if (ipl_info.type == IPL_TYPE_CCW)
856 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; 924 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
857 reipl_capabilities |= IPL_TYPE_CCW; 925 reipl_capabilities |= IPL_TYPE_CCW;
858 return 0; 926 return 0;
@@ -862,9 +930,9 @@ static int __init reipl_fcp_init(void)
862{ 930{
863 int rc; 931 int rc;
864 932
865 if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP)) 933 if ((!diag308_set_works) && (ipl_info.type != IPL_TYPE_FCP))
866 return 0; 934 return 0;
867 if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP)) 935 if ((!diag308_set_works) && (ipl_info.type == IPL_TYPE_FCP))
868 make_attrs_ro(reipl_fcp_attrs); 936 make_attrs_ro(reipl_fcp_attrs);
869 937
870 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); 938 reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
@@ -875,7 +943,7 @@ static int __init reipl_fcp_init(void)
875 free_page((unsigned long)reipl_block_fcp); 943 free_page((unsigned long)reipl_block_fcp);
876 return rc; 944 return rc;
877 } 945 }
878 if (ipl_get_type() == IPL_TYPE_FCP) { 946 if (ipl_info.type == IPL_TYPE_FCP) {
879 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE); 947 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
880 } else { 948 } else {
881 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; 949 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
@@ -909,7 +977,7 @@ static int __init reipl_init(void)
909 rc = reipl_nss_init(); 977 rc = reipl_nss_init();
910 if (rc) 978 if (rc)
911 return rc; 979 return rc;
912 rc = reipl_set_type(ipl_get_type()); 980 rc = reipl_set_type(ipl_info.type);
913 if (rc) 981 if (rc)
914 return rc; 982 return rc;
915 return 0; 983 return 0;
@@ -931,7 +999,7 @@ static int __init dump_ccw_init(void)
931 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; 999 dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
932 dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN; 1000 dump_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
933 dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; 1001 dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
934 dump_capabilities |= IPL_TYPE_CCW; 1002 dump_capabilities |= DUMP_TYPE_CCW;
935 return 0; 1003 return 0;
936} 1004}
937 1005
@@ -956,7 +1024,7 @@ static int __init dump_fcp_init(void)
956 dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; 1024 dump_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
957 dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP; 1025 dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP;
958 dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP; 1026 dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP;
959 dump_capabilities |= IPL_TYPE_FCP; 1027 dump_capabilities |= DUMP_TYPE_FCP;
960 return 0; 1028 return 0;
961} 1029}
962 1030
@@ -995,7 +1063,7 @@ static int __init dump_init(void)
995 rc = dump_fcp_init(); 1063 rc = dump_fcp_init();
996 if (rc) 1064 if (rc)
997 return rc; 1065 return rc;
998 dump_set_type(IPL_TYPE_NONE); 1066 dump_set_type(DUMP_TYPE_NONE);
999 return 0; 1067 return 0;
1000} 1068}
1001 1069
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 863c8d08c026..3dfd0985861c 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -285,6 +285,26 @@ static void __init conmode_default(void)
285 } 285 }
286} 286}
287 287
288#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
289static void __init setup_zfcpdump(unsigned int console_devno)
290{
291 static char str[64];
292
293 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
294 return;
295 if (console_devno != -1)
296 sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x",
297 ipl_info.data.fcp.dev_id.devno, console_devno);
298 else
299 sprintf(str, "cio_ignore=all,!0.0.%04x",
300 ipl_info.data.fcp.dev_id.devno);
301 strcat(COMMAND_LINE, str);
302 console_loglevel = 2;
303}
304#else
305static inline void setup_zfcpdump(unsigned int console_devno) {}
306#endif /* CONFIG_ZFCPDUMP */
307
288#ifdef CONFIG_SMP 308#ifdef CONFIG_SMP
289void (*_machine_restart)(char *command) = machine_restart_smp; 309void (*_machine_restart)(char *command) = machine_restart_smp;
290void (*_machine_halt)(void) = machine_halt_smp; 310void (*_machine_halt)(void) = machine_halt_smp;
@@ -586,13 +606,20 @@ setup_resources(void)
586 } 606 }
587} 607}
588 608
609unsigned long real_memory_size;
610EXPORT_SYMBOL_GPL(real_memory_size);
611
589static void __init setup_memory_end(void) 612static void __init setup_memory_end(void)
590{ 613{
591 unsigned long real_size, memory_size; 614 unsigned long memory_size;
592 unsigned long max_mem, max_phys; 615 unsigned long max_mem, max_phys;
593 int i; 616 int i;
594 617
595 memory_size = real_size = 0; 618#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
619 if (ipl_info.type == IPL_TYPE_FCP_DUMP)
620 memory_end = ZFCPDUMP_HSA_SIZE;
621#endif
622 memory_size = 0;
596 max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE; 623 max_phys = VMALLOC_END_INIT - VMALLOC_MIN_SIZE;
597 memory_end &= PAGE_MASK; 624 memory_end &= PAGE_MASK;
598 625
@@ -601,7 +628,8 @@ static void __init setup_memory_end(void)
601 for (i = 0; i < MEMORY_CHUNKS; i++) { 628 for (i = 0; i < MEMORY_CHUNKS; i++) {
602 struct mem_chunk *chunk = &memory_chunk[i]; 629 struct mem_chunk *chunk = &memory_chunk[i];
603 630
604 real_size = max(real_size, chunk->addr + chunk->size); 631 real_memory_size = max(real_memory_size,
632 chunk->addr + chunk->size);
605 if (chunk->addr >= max_mem) { 633 if (chunk->addr >= max_mem) {
606 memset(chunk, 0, sizeof(*chunk)); 634 memset(chunk, 0, sizeof(*chunk));
607 continue; 635 continue;
@@ -765,6 +793,7 @@ setup_arch(char **cmdline_p)
765 793
766 parse_early_param(); 794 parse_early_param();
767 795
796 setup_ipl_info();
768 setup_memory_end(); 797 setup_memory_end();
769 setup_addressing_mode(); 798 setup_addressing_mode();
770 setup_memory(); 799 setup_memory();
@@ -782,6 +811,9 @@ setup_arch(char **cmdline_p)
782 811
783 /* Setup default console */ 812 /* Setup default console */
784 conmode_default(); 813 conmode_default();
814
815 /* Setup zfcpdump support */
816 setup_zfcpdump(console_devno);
785} 817}
786 818
787void print_cpu_info(struct cpuinfo_S390 *cpuinfo) 819void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 97764f710bb7..7c0143fdf710 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -31,6 +31,7 @@
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/cpu.h> 32#include <linux/cpu.h>
33#include <linux/timex.h> 33#include <linux/timex.h>
34#include <linux/bootmem.h>
34#include <asm/ipl.h> 35#include <asm/ipl.h>
35#include <asm/setup.h> 36#include <asm/setup.h>
36#include <asm/sigp.h> 37#include <asm/sigp.h>
@@ -40,6 +41,7 @@
40#include <asm/cpcmd.h> 41#include <asm/cpcmd.h>
41#include <asm/tlbflush.h> 42#include <asm/tlbflush.h>
42#include <asm/timer.h> 43#include <asm/timer.h>
44#include <asm/lowcore.h>
43 45
44extern volatile int __cpu_logical_map[]; 46extern volatile int __cpu_logical_map[];
45 47
@@ -395,6 +397,65 @@ void smp_ctl_clear_bit(int cr, int bit)
395 on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1); 397 on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
396} 398}
397 399
400#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
401
402/*
403 * zfcpdump_prefix_array holds prefix registers for the following scenario:
404 * 64 bit zfcpdump kernel and 31 bit kernel which is to be dumped. We have to
405 * save its prefix registers, since they get lost, when switching from 31 bit
406 * to 64 bit.
407 */
408unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
409 __attribute__((__section__(".data")));
410
411static void __init smp_get_save_areas(void)
412{
413 unsigned int cpu, cpu_num, rc;
414 __u16 boot_cpu_addr;
415
416 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
417 return;
418 boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
419 cpu_num = 1;
420 for (cpu = 0; cpu <= 65535; cpu++) {
421 if ((u16) cpu == boot_cpu_addr)
422 continue;
423 __cpu_logical_map[1] = (__u16) cpu;
424 if (signal_processor(1, sigp_sense) == sigp_not_operational)
425 continue;
426 if (cpu_num >= NR_CPUS) {
427 printk("WARNING: Registers for cpu %i are not "
428 "saved, since dump kernel was compiled with"
429 "NR_CPUS=%i!\n", cpu_num, NR_CPUS);
430 continue;
431 }
432 zfcpdump_save_areas[cpu_num] =
433 alloc_bootmem(sizeof(union save_area));
434 while (1) {
435 rc = signal_processor(1, sigp_stop_and_store_status);
436 if (rc != sigp_busy)
437 break;
438 cpu_relax();
439 }
440 memcpy(zfcpdump_save_areas[cpu_num],
441 (void *)(unsigned long) store_prefix() +
442 SAVE_AREA_BASE, SAVE_AREA_SIZE);
443#ifdef __s390x__
444 /* copy original prefix register */
445 zfcpdump_save_areas[cpu_num]->s390x.pref_reg =
446 zfcpdump_prefix_array[cpu_num];
447#endif
448 cpu_num++;
449 }
450}
451
452union save_area *zfcpdump_save_areas[NR_CPUS + 1];
453EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
454
455#else
456#define smp_get_save_areas() do { } while (0)
457#endif
458
398/* 459/*
399 * Lets check how many CPUs we have. 460 * Lets check how many CPUs we have.
400 */ 461 */
@@ -589,6 +650,7 @@ void __init smp_setup_cpu_possible_map(void)
589{ 650{
590 unsigned int phy_cpus, pos_cpus, cpu; 651 unsigned int phy_cpus, pos_cpus, cpu;
591 652
653 smp_get_save_areas();
592 phy_cpus = smp_count_cpus(); 654 phy_cpus = smp_count_cpus();
593 pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS); 655 pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
594 656