aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/cpcmd.c18
-rw-r--r--arch/s390/kernel/head.S21
-rw-r--r--arch/s390/kernel/head31.S8
-rw-r--r--arch/s390/kernel/head64.S17
-rw-r--r--arch/s390/kernel/ipl.c185
-rw-r--r--arch/s390/kernel/machine_kexec.c78
-rw-r--r--arch/s390/kernel/reipl.S17
-rw-r--r--arch/s390/kernel/reipl64.S16
-rw-r--r--arch/s390/kernel/relocate_kernel.S5
-rw-r--r--arch/s390/kernel/relocate_kernel64.S5
-rw-r--r--arch/s390/kernel/reset.S48
-rw-r--r--arch/s390/kernel/setup.c66
-rw-r--r--arch/s390/kernel/smp.c117
-rw-r--r--arch/s390/kernel/traps.c30
15 files changed, 337 insertions, 296 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index aa978978d3d1..a81881c9b297 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -4,7 +4,7 @@
4 4
5EXTRA_AFLAGS := -traditional 5EXTRA_AFLAGS := -traditional
6 6
7obj-y := bitmap.o traps.o time.o process.o \ 7obj-y := bitmap.o traps.o time.o process.o reset.o \
8 setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ 8 setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
9 semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o 9 semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o
10 10
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 1eae74e72f95..a5972f1541fe 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -21,14 +21,15 @@ static DEFINE_SPINLOCK(cpcmd_lock);
21static char cpcmd_buf[241]; 21static char cpcmd_buf[241];
22 22
23/* 23/*
24 * the caller of __cpcmd has to ensure that the response buffer is below 2 GB 24 * __cpcmd has some restrictions over cpcmd
25 * - the response buffer must reside below 2GB (if any)
26 * - __cpcmd is unlocked and therefore not SMP-safe
25 */ 27 */
26int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) 28int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
27{ 29{
28 unsigned long flags, cmdlen; 30 unsigned cmdlen;
29 int return_code, return_len; 31 int return_code, return_len;
30 32
31 spin_lock_irqsave(&cpcmd_lock, flags);
32 cmdlen = strlen(cmd); 33 cmdlen = strlen(cmd);
33 BUG_ON(cmdlen > 240); 34 BUG_ON(cmdlen > 240);
34 memcpy(cpcmd_buf, cmd, cmdlen); 35 memcpy(cpcmd_buf, cmd, cmdlen);
@@ -74,7 +75,6 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
74 : "+d" (reg3) : "d" (reg2) : "cc"); 75 : "+d" (reg3) : "d" (reg2) : "cc");
75 return_code = (int) reg3; 76 return_code = (int) reg3;
76 } 77 }
77 spin_unlock_irqrestore(&cpcmd_lock, flags);
78 if (response_code != NULL) 78 if (response_code != NULL)
79 *response_code = return_code; 79 *response_code = return_code;
80 return return_len; 80 return return_len;
@@ -82,15 +82,18 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
82 82
83EXPORT_SYMBOL(__cpcmd); 83EXPORT_SYMBOL(__cpcmd);
84 84
85#ifdef CONFIG_64BIT
86int cpcmd(const char *cmd, char *response, int rlen, int *response_code) 85int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
87{ 86{
88 char *lowbuf; 87 char *lowbuf;
89 int len; 88 int len;
89 unsigned long flags;
90 90
91 if ((rlen == 0) || (response == NULL) 91 if ((rlen == 0) || (response == NULL)
92 || !((unsigned long)response >> 31)) 92 || !((unsigned long)response >> 31)) {
93 spin_lock_irqsave(&cpcmd_lock, flags);
93 len = __cpcmd(cmd, response, rlen, response_code); 94 len = __cpcmd(cmd, response, rlen, response_code);
95 spin_unlock_irqrestore(&cpcmd_lock, flags);
96 }
94 else { 97 else {
95 lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); 98 lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
96 if (!lowbuf) { 99 if (!lowbuf) {
@@ -98,7 +101,9 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
98 "cpcmd: could not allocate response buffer\n"); 101 "cpcmd: could not allocate response buffer\n");
99 return -ENOMEM; 102 return -ENOMEM;
100 } 103 }
104 spin_lock_irqsave(&cpcmd_lock, flags);
101 len = __cpcmd(cmd, lowbuf, rlen, response_code); 105 len = __cpcmd(cmd, lowbuf, rlen, response_code);
106 spin_unlock_irqrestore(&cpcmd_lock, flags);
102 memcpy(response, lowbuf, rlen); 107 memcpy(response, lowbuf, rlen);
103 kfree(lowbuf); 108 kfree(lowbuf);
104 } 109 }
@@ -106,4 +111,3 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
106} 111}
107 112
108EXPORT_SYMBOL(cpcmd); 113EXPORT_SYMBOL(cpcmd);
109#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 0cf59bb7a857..8f8c802f1bcf 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -418,24 +418,6 @@ start:
418.gotr: 418.gotr:
419 l %r10,.tbl # EBCDIC to ASCII table 419 l %r10,.tbl # EBCDIC to ASCII table
420 tr 0(240,%r8),0(%r10) 420 tr 0(240,%r8),0(%r10)
421 stidp __LC_CPUID # Are we running on VM maybe
422 cli __LC_CPUID,0xff
423 bnz .test
424 .long 0x83300060 # diag 3,0,x'0060' - storage size
425 b .done
426.test:
427 mvc 0x68(8),.pgmnw # set up pgm check handler
428 l %r2,.fourmeg
429 lr %r3,%r2
430 bctr %r3,%r0 # 4M-1
431.loop: iske %r0,%r3
432 ar %r3,%r2
433.pgmx:
434 sr %r3,%r2
435 la %r3,1(%r3)
436.done:
437 l %r1,.memsize
438 st %r3,ARCH_OFFSET(%r1)
439 slr %r0,%r0 421 slr %r0,%r0
440 st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11) 422 st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
441 st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11) 423 st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
@@ -443,9 +425,6 @@ start:
443.tbl: .long _ebcasc # translate table 425.tbl: .long _ebcasc # translate table
444.cmd: .long COMMAND_LINE # address of command line buffer 426.cmd: .long COMMAND_LINE # address of command line buffer
445.parm: .long PARMAREA 427.parm: .long PARMAREA
446.memsize: .long memory_size
447.fourmeg: .long 0x00400000 # 4M
448.pgmnw: .long 0x00080000,.pgmx
449.lowcase: 428.lowcase:
450 .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 429 .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
451 .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f 430 .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 0a2c929486ab..4388b3309e0c 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -131,10 +131,11 @@ startup_continue:
131 .long init_thread_union 131 .long init_thread_union
132.Lpmask: 132.Lpmask:
133 .byte 0 133 .byte 0
134.align 8 134 .align 8
135.Lpcext:.long 0x00080000,0x80000000 135.Lpcext:.long 0x00080000,0x80000000
136.Lcr: 136.Lcr:
137 .long 0x00 # place holder for cr0 137 .long 0x00 # place holder for cr0
138 .align 8
138.Lwaitsclp: 139.Lwaitsclp:
139 .long 0x010a0000,0x80000000 + .Lsclph 140 .long 0x010a0000,0x80000000 + .Lsclph
140.Lrcp: 141.Lrcp:
@@ -156,7 +157,7 @@ startup_continue:
156 slr %r4,%r4 # set start of chunk to zero 157 slr %r4,%r4 # set start of chunk to zero
157 slr %r5,%r5 # set end of chunk to zero 158 slr %r5,%r5 # set end of chunk to zero
158 slr %r6,%r6 # set access code to zero 159 slr %r6,%r6 # set access code to zero
159 la %r10, MEMORY_CHUNKS # number of chunks 160 la %r10,MEMORY_CHUNKS # number of chunks
160.Lloop: 161.Lloop:
161 tprot 0(%r5),0 # test protection of first byte 162 tprot 0(%r5),0 # test protection of first byte
162 ipm %r7 163 ipm %r7
@@ -176,8 +177,6 @@ startup_continue:
176 st %r0,4(%r3) # store size of chunk 177 st %r0,4(%r3) # store size of chunk
177 st %r6,8(%r3) # store type of chunk 178 st %r6,8(%r3) # store type of chunk
178 la %r3,12(%r3) 179 la %r3,12(%r3)
179 l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size
180 st %r5,0(%r4) # store last end to memory size
181 ahi %r10,-1 # update chunk number 180 ahi %r10,-1 # update chunk number
182.Lchkloop: 181.Lchkloop:
183 lr %r6,%r7 # set access code to last cc 182 lr %r6,%r7 # set access code to last cc
@@ -292,7 +291,6 @@ startup_continue:
292.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg 291.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
293.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte 292.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
294.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c 293.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c
295.Lmemsize:.long memory_size
296.Lmchunk:.long memory_chunk 294.Lmchunk:.long memory_chunk
297.Lmflags:.long machine_flags 295.Lmflags:.long machine_flags
298.Lbss_bgn: .long __bss_start 296.Lbss_bgn: .long __bss_start
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 42f54d482441..c526279e1123 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -70,7 +70,20 @@ startup_continue:
70 sgr %r5,%r5 # set src,length and pad to zero 70 sgr %r5,%r5 # set src,length and pad to zero
71 mvcle %r2,%r4,0 # clear mem 71 mvcle %r2,%r4,0 # clear mem
72 jo .-4 # branch back, if not finish 72 jo .-4 # branch back, if not finish
73 # set program check new psw mask
74 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
75 larl %r1,.Lslowmemdetect # set program check address
76 stg %r1,__LC_PGM_NEW_PSW+8
77 lghi %r1,0xc
78 diag %r0,%r1,0x260 # get memory size of virtual machine
79 cgr %r0,%r1 # different? -> old detection routine
80 jne .Lslowmemdetect
81 aghi %r1,1 # size is one more than end
82 larl %r2,memory_chunk
83 stg %r1,8(%r2) # store size of chunk
84 j .Ldonemem
73 85
86.Lslowmemdetect:
74 l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word 87 l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
75.Lservicecall: 88.Lservicecall:
76 stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts 89 stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
@@ -139,8 +152,6 @@ startup_continue:
139 .int 0x100000 152 .int 0x100000
140 153
141.Lfchunk: 154.Lfchunk:
142 # set program check new psw mask
143 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
144 155
145# 156#
146# find memory chunks. 157# find memory chunks.
@@ -175,8 +186,6 @@ startup_continue:
175 stg %r0,8(%r3) # store size of chunk 186 stg %r0,8(%r3) # store size of chunk
176 st %r6,20(%r3) # store type of chunk 187 st %r6,20(%r3) # store type of chunk
177 la %r3,24(%r3) 188 la %r3,24(%r3)
178 larl %r8,memory_size
179 stg %r5,0(%r8) # store memory size
180 ahi %r10,-1 # update chunk number 189 ahi %r10,-1 # update chunk number
181.Lchkloop: 190.Lchkloop:
182 lr %r6,%r7 # set access code to last cc 191 lr %r6,%r7 # set access code to last cc
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 1f5e782b3d05..a36bea1188d9 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -13,12 +13,21 @@
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/reboot.h> 15#include <linux/reboot.h>
16#include <linux/ctype.h>
16#include <asm/smp.h> 17#include <asm/smp.h>
17#include <asm/setup.h> 18#include <asm/setup.h>
18#include <asm/cpcmd.h> 19#include <asm/cpcmd.h>
19#include <asm/cio.h> 20#include <asm/cio.h>
21#include <asm/ebcdic.h>
22#include <asm/reset.h>
20 23
21#define IPL_PARM_BLOCK_VERSION 0 24#define IPL_PARM_BLOCK_VERSION 0
25#define LOADPARM_LEN 8
26
27extern char s390_readinfo_sccb[];
28#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010)
29#define SCCB_LOADPARM (&s390_readinfo_sccb[24])
30#define SCCB_FLAG (s390_readinfo_sccb[91])
22 31
23enum ipl_type { 32enum ipl_type {
24 IPL_TYPE_NONE = 1, 33 IPL_TYPE_NONE = 1,
@@ -289,9 +298,25 @@ static struct attribute_group ipl_fcp_attr_group = {
289 298
290/* CCW ipl device attributes */ 299/* CCW ipl device attributes */
291 300
301static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
302{
303 char loadparm[LOADPARM_LEN + 1] = {};
304
305 if (!SCCB_VALID)
306 return sprintf(page, "#unknown#\n");
307 memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
308 EBCASC(loadparm, LOADPARM_LEN);
309 strstrip(loadparm);
310 return sprintf(page, "%s\n", loadparm);
311}
312
313static struct subsys_attribute sys_ipl_ccw_loadparm_attr =
314 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
315
292static struct attribute *ipl_ccw_attrs[] = { 316static struct attribute *ipl_ccw_attrs[] = {
293 &sys_ipl_type_attr.attr, 317 &sys_ipl_type_attr.attr,
294 &sys_ipl_device_attr.attr, 318 &sys_ipl_device_attr.attr,
319 &sys_ipl_ccw_loadparm_attr.attr,
295 NULL, 320 NULL,
296}; 321};
297 322
@@ -348,8 +373,57 @@ static struct attribute_group reipl_fcp_attr_group = {
348DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", 373DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
349 reipl_block_ccw->ipl_info.ccw.devno); 374 reipl_block_ccw->ipl_info.ccw.devno);
350 375
376static void reipl_get_ascii_loadparm(char *loadparm)
377{
378 memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
379 LOADPARM_LEN);
380 EBCASC(loadparm, LOADPARM_LEN);
381 loadparm[LOADPARM_LEN] = 0;
382 strstrip(loadparm);
383}
384
385static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
386{
387 char buf[LOADPARM_LEN + 1];
388
389 reipl_get_ascii_loadparm(buf);
390 return sprintf(page, "%s\n", buf);
391}
392
393static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
394 const char *buf, size_t len)
395{
396 int i, lp_len;
397
398 /* ignore trailing newline */
399 lp_len = len;
400 if ((len > 0) && (buf[len - 1] == '\n'))
401 lp_len--;
402 /* loadparm can have max 8 characters and must not start with a blank */
403 if ((lp_len > LOADPARM_LEN) || ((lp_len > 0) && (buf[0] == ' ')))
404 return -EINVAL;
405 /* loadparm can only contain "a-z,A-Z,0-9,SP,." */
406 for (i = 0; i < lp_len; i++) {
407 if (isalpha(buf[i]) || isdigit(buf[i]) || (buf[i] == ' ') ||
408 (buf[i] == '.'))
409 continue;
410 return -EINVAL;
411 }
412 /* initialize loadparm with blanks */
413 memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
414 /* copy and convert to ebcdic */
415 memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
416 ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
417 return len;
418}
419
420static struct subsys_attribute sys_reipl_ccw_loadparm_attr =
421 __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
422 reipl_ccw_loadparm_store);
423
351static struct attribute *reipl_ccw_attrs[] = { 424static struct attribute *reipl_ccw_attrs[] = {
352 &sys_reipl_ccw_device_attr.attr, 425 &sys_reipl_ccw_device_attr.attr,
426 &sys_reipl_ccw_loadparm_attr.attr,
353 NULL, 427 NULL,
354}; 428};
355 429
@@ -502,23 +576,6 @@ static struct subsys_attribute dump_type_attr =
502 576
503static decl_subsys(dump, NULL, NULL); 577static decl_subsys(dump, NULL, NULL);
504 578
505#ifdef CONFIG_SMP
506static void dump_smp_stop_all(void)
507{
508 int cpu;
509 preempt_disable();
510 for_each_online_cpu(cpu) {
511 if (cpu == smp_processor_id())
512 continue;
513 while (signal_processor(cpu, sigp_stop) == sigp_busy)
514 udelay(10);
515 }
516 preempt_enable();
517}
518#else
519#define dump_smp_stop_all() do { } while (0)
520#endif
521
522/* 579/*
523 * Shutdown actions section 580 * Shutdown actions section
524 */ 581 */
@@ -571,11 +628,14 @@ void do_reipl(void)
571{ 628{
572 struct ccw_dev_id devid; 629 struct ccw_dev_id devid;
573 static char buf[100]; 630 static char buf[100];
631 char loadparm[LOADPARM_LEN + 1];
574 632
575 switch (reipl_type) { 633 switch (reipl_type) {
576 case IPL_TYPE_CCW: 634 case IPL_TYPE_CCW:
635 reipl_get_ascii_loadparm(loadparm);
577 printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n", 636 printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n",
578 reipl_block_ccw->ipl_info.ccw.devno); 637 reipl_block_ccw->ipl_info.ccw.devno);
638 printk(KERN_EMERG "loadparm = '%s'\n", loadparm);
579 break; 639 break;
580 case IPL_TYPE_FCP: 640 case IPL_TYPE_FCP:
581 printk(KERN_EMERG "reboot on fcp device:\n"); 641 printk(KERN_EMERG "reboot on fcp device:\n");
@@ -588,12 +648,19 @@ void do_reipl(void)
588 switch (reipl_method) { 648 switch (reipl_method) {
589 case IPL_METHOD_CCW_CIO: 649 case IPL_METHOD_CCW_CIO:
590 devid.devno = reipl_block_ccw->ipl_info.ccw.devno; 650 devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
651 if (ipl_get_type() == IPL_TYPE_CCW && devid.devno == ipl_devno)
652 diag308(DIAG308_IPL, NULL);
591 devid.ssid = 0; 653 devid.ssid = 0;
592 reipl_ccw_dev(&devid); 654 reipl_ccw_dev(&devid);
593 break; 655 break;
594 case IPL_METHOD_CCW_VM: 656 case IPL_METHOD_CCW_VM:
595 sprintf(buf, "IPL %X", reipl_block_ccw->ipl_info.ccw.devno); 657 if (strlen(loadparm) == 0)
596 cpcmd(buf, NULL, 0, NULL); 658 sprintf(buf, "IPL %X",
659 reipl_block_ccw->ipl_info.ccw.devno);
660 else
661 sprintf(buf, "IPL %X LOADPARM '%s'",
662 reipl_block_ccw->ipl_info.ccw.devno, loadparm);
663 __cpcmd(buf, NULL, 0, NULL);
597 break; 664 break;
598 case IPL_METHOD_CCW_DIAG: 665 case IPL_METHOD_CCW_DIAG:
599 diag308(DIAG308_SET, reipl_block_ccw); 666 diag308(DIAG308_SET, reipl_block_ccw);
@@ -607,16 +674,17 @@ void do_reipl(void)
607 diag308(DIAG308_IPL, NULL); 674 diag308(DIAG308_IPL, NULL);
608 break; 675 break;
609 case IPL_METHOD_FCP_RO_VM: 676 case IPL_METHOD_FCP_RO_VM:
610 cpcmd("IPL", NULL, 0, NULL); 677 __cpcmd("IPL", NULL, 0, NULL);
611 break; 678 break;
612 case IPL_METHOD_NONE: 679 case IPL_METHOD_NONE:
613 default: 680 default:
614 if (MACHINE_IS_VM) 681 if (MACHINE_IS_VM)
615 cpcmd("IPL", NULL, 0, NULL); 682 __cpcmd("IPL", NULL, 0, NULL);
616 diag308(DIAG308_IPL, NULL); 683 diag308(DIAG308_IPL, NULL);
617 break; 684 break;
618 } 685 }
619 panic("reipl failed!\n"); 686 printk(KERN_EMERG "reboot failed!\n");
687 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
620} 688}
621 689
622static void do_dump(void) 690static void do_dump(void)
@@ -639,17 +707,17 @@ static void do_dump(void)
639 707
640 switch (dump_method) { 708 switch (dump_method) {
641 case IPL_METHOD_CCW_CIO: 709 case IPL_METHOD_CCW_CIO:
642 dump_smp_stop_all(); 710 smp_send_stop();
643 devid.devno = dump_block_ccw->ipl_info.ccw.devno; 711 devid.devno = dump_block_ccw->ipl_info.ccw.devno;
644 devid.ssid = 0; 712 devid.ssid = 0;
645 reipl_ccw_dev(&devid); 713 reipl_ccw_dev(&devid);
646 break; 714 break;
647 case IPL_METHOD_CCW_VM: 715 case IPL_METHOD_CCW_VM:
648 dump_smp_stop_all(); 716 smp_send_stop();
649 sprintf(buf, "STORE STATUS"); 717 sprintf(buf, "STORE STATUS");
650 cpcmd(buf, NULL, 0, NULL); 718 __cpcmd(buf, NULL, 0, NULL);
651 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); 719 sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
652 cpcmd(buf, NULL, 0, NULL); 720 __cpcmd(buf, NULL, 0, NULL);
653 break; 721 break;
654 case IPL_METHOD_CCW_DIAG: 722 case IPL_METHOD_CCW_DIAG:
655 diag308(DIAG308_SET, dump_block_ccw); 723 diag308(DIAG308_SET, dump_block_ccw);
@@ -746,6 +814,17 @@ static int __init reipl_ccw_init(void)
746 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; 814 reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
747 reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw); 815 reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw);
748 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; 816 reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
817 /* check if read scp info worked and set loadparm */
818 if (SCCB_VALID)
819 memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
820 SCCB_LOADPARM, LOADPARM_LEN);
821 else
822 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
823 memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
824 LOADPARM_LEN);
825 /* FIXME: check for diag308_set_works when enabling diag ccw reipl */
826 if (!MACHINE_IS_VM)
827 sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
749 if (ipl_get_type() == IPL_TYPE_CCW) 828 if (ipl_get_type() == IPL_TYPE_CCW)
750 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; 829 reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
751 reipl_capabilities |= IPL_TYPE_CCW; 830 reipl_capabilities |= IPL_TYPE_CCW;
@@ -827,13 +906,11 @@ static int __init dump_ccw_init(void)
827 return 0; 906 return 0;
828} 907}
829 908
830extern char s390_readinfo_sccb[];
831
832static int __init dump_fcp_init(void) 909static int __init dump_fcp_init(void)
833{ 910{
834 int rc; 911 int rc;
835 912
836 if(!(s390_readinfo_sccb[91] & 0x2)) 913 if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
837 return 0; /* LDIPL DUMP is not installed */ 914 return 0; /* LDIPL DUMP is not installed */
838 if (!diag308_set_works) 915 if (!diag308_set_works)
839 return 0; 916 return 0;
@@ -931,3 +1008,53 @@ static int __init s390_ipl_init(void)
931} 1008}
932 1009
933__initcall(s390_ipl_init); 1010__initcall(s390_ipl_init);
1011
1012static LIST_HEAD(rcall);
1013static DEFINE_MUTEX(rcall_mutex);
1014
1015void register_reset_call(struct reset_call *reset)
1016{
1017 mutex_lock(&rcall_mutex);
1018 list_add(&reset->list, &rcall);
1019 mutex_unlock(&rcall_mutex);
1020}
1021EXPORT_SYMBOL_GPL(register_reset_call);
1022
1023void unregister_reset_call(struct reset_call *reset)
1024{
1025 mutex_lock(&rcall_mutex);
1026 list_del(&reset->list);
1027 mutex_unlock(&rcall_mutex);
1028}
1029EXPORT_SYMBOL_GPL(unregister_reset_call);
1030
1031static void do_reset_calls(void)
1032{
1033 struct reset_call *reset;
1034
1035 list_for_each_entry(reset, &rcall, list)
1036 reset->fn();
1037}
1038
1039extern void reset_mcck_handler(void);
1040
1041void s390_reset_system(void)
1042{
1043 struct _lowcore *lc;
1044
1045 /* Stack for interrupt/machine check handler */
1046 lc = (struct _lowcore *)(unsigned long) store_prefix();
1047 lc->panic_stack = S390_lowcore.panic_stack;
1048
1049 /* Disable prefixing */
1050 set_prefix(0);
1051
1052 /* Disable lowcore protection */
1053 __ctl_clear_bit(0,28);
1054
1055 /* Set new machine check handler */
1056 S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
1057 S390_lowcore.mcck_new_psw.addr =
1058 PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
1059 do_reset_calls();
1060}
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 60b1ea9f946b..f6d9bcc0f75b 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -1,15 +1,10 @@
1/* 1/*
2 * arch/s390/kernel/machine_kexec.c 2 * arch/s390/kernel/machine_kexec.c
3 * 3 *
4 * (C) Copyright IBM Corp. 2005 4 * Copyright IBM Corp. 2005,2006
5 * 5 *
6 * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com> 6 * Author(s): Rolf Adelsberger,
7 * 7 * Heiko Carstens <heiko.carstens@de.ibm.com>
8 */
9
10/*
11 * s390_machine_kexec.c - handle the transition of Linux booting another kernel
12 * on the S390 architecture.
13 */ 8 */
14 9
15#include <linux/device.h> 10#include <linux/device.h>
@@ -22,86 +17,49 @@
22#include <asm/pgalloc.h> 17#include <asm/pgalloc.h>
23#include <asm/system.h> 18#include <asm/system.h>
24#include <asm/smp.h> 19#include <asm/smp.h>
20#include <asm/reset.h>
25 21
26static void kexec_halt_all_cpus(void *); 22typedef void (*relocate_kernel_t)(kimage_entry_t *, unsigned long);
27
28typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
29 23
30extern const unsigned char relocate_kernel[]; 24extern const unsigned char relocate_kernel[];
31extern const unsigned long long relocate_kernel_len; 25extern const unsigned long long relocate_kernel_len;
32 26
33int 27int machine_kexec_prepare(struct kimage *image)
34machine_kexec_prepare(struct kimage *image)
35{ 28{
36 unsigned long reboot_code_buffer; 29 void *reboot_code_buffer;
37 30
38 /* We don't support anything but the default image type for now. */ 31 /* We don't support anything but the default image type for now. */
39 if (image->type != KEXEC_TYPE_DEFAULT) 32 if (image->type != KEXEC_TYPE_DEFAULT)
40 return -EINVAL; 33 return -EINVAL;
41 34
42 /* Get the destination where the assembler code should be copied to.*/ 35 /* Get the destination where the assembler code should be copied to.*/
43 reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT; 36 reboot_code_buffer = (void *) page_to_phys(image->control_code_page);
44 37
45 /* Then copy it */ 38 /* Then copy it */
46 memcpy((void *) reboot_code_buffer, relocate_kernel, 39 memcpy(reboot_code_buffer, relocate_kernel, relocate_kernel_len);
47 relocate_kernel_len);
48 return 0; 40 return 0;
49} 41}
50 42
51void 43void machine_kexec_cleanup(struct kimage *image)
52machine_kexec_cleanup(struct kimage *image)
53{ 44{
54} 45}
55 46
56void 47void machine_shutdown(void)
57machine_shutdown(void)
58{ 48{
59 printk(KERN_INFO "kexec: machine_shutdown called\n"); 49 printk(KERN_INFO "kexec: machine_shutdown called\n");
60} 50}
61 51
62NORET_TYPE void 52void machine_kexec(struct kimage *image)
63machine_kexec(struct kimage *image)
64{ 53{
65 clear_all_subchannels();
66 cio_reset_channel_paths();
67
68 /* Disable lowcore protection */
69 ctl_clear_bit(0,28);
70
71 on_each_cpu(kexec_halt_all_cpus, image, 0, 0);
72 for (;;);
73}
74
75extern void pfault_fini(void);
76
77static void
78kexec_halt_all_cpus(void *kernel_image)
79{
80 static atomic_t cpuid = ATOMIC_INIT(-1);
81 int cpu;
82 struct kimage *image;
83 relocate_kernel_t data_mover; 54 relocate_kernel_t data_mover;
84 55
85#ifdef CONFIG_PFAULT 56 smp_send_stop();
86 if (MACHINE_IS_VM) 57 pfault_fini();
87 pfault_fini(); 58 s390_reset_system();
88#endif
89 59
90 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) 60 data_mover = (relocate_kernel_t) page_to_phys(image->control_code_page);
91 signal_processor(smp_processor_id(), sigp_stop);
92
93 /* Wait for all other cpus to enter stopped state */
94 for_each_online_cpu(cpu) {
95 if (cpu == smp_processor_id())
96 continue;
97 while (!smp_cpu_not_running(cpu))
98 cpu_relax();
99 }
100
101 image = (struct kimage *) kernel_image;
102 data_mover = (relocate_kernel_t)
103 (page_to_pfn(image->control_code_page) << PAGE_SHIFT);
104 61
105 /* Call the moving routine */ 62 /* Call the moving routine */
106 (*data_mover) (&image->head, image->start); 63 (*data_mover)(&image->head, image->start);
64 for (;;);
107} 65}
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index 0340477f3b08..f9434d42ce9f 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -11,19 +11,10 @@
11 .globl do_reipl_asm 11 .globl do_reipl_asm
12do_reipl_asm: basr %r13,0 12do_reipl_asm: basr %r13,0
13.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) 13.Lpg0: lpsw .Lnewpsw-.Lpg0(%r13)
14 14.Lpg1: # do store status of all registers
15 # switch off lowcore protection
16
17.Lpg1: stctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
18 stctl %c0,%c0,.Lctlsave2-.Lpg0(%r13)
19 ni .Lctlsave1-.Lpg0(%r13),0xef
20 lctl %c0,%c0,.Lctlsave1-.Lpg0(%r13)
21
22 # do store status of all registers
23 15
24 stm %r0,%r15,__LC_GPREGS_SAVE_AREA 16 stm %r0,%r15,__LC_GPREGS_SAVE_AREA
25 stctl %c0,%c15,__LC_CREGS_SAVE_AREA 17 stctl %c0,%c15,__LC_CREGS_SAVE_AREA
26 mvc __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13)
27 stam %a0,%a15,__LC_AREGS_SAVE_AREA 18 stam %a0,%a15,__LC_AREGS_SAVE_AREA
28 stpx __LC_PREFIX_SAVE_AREA 19 stpx __LC_PREFIX_SAVE_AREA
29 stckc .Lclkcmp-.Lpg0(%r13) 20 stckc .Lclkcmp-.Lpg0(%r13)
@@ -56,8 +47,7 @@ do_reipl_asm: basr %r13,0
56.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 47.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
57 jz .L003 48 jz .L003
58 bas %r14,.Ldisab-.Lpg0(%r13) 49 bas %r14,.Ldisab-.Lpg0(%r13)
59.L003: spx .Lnull-.Lpg0(%r13) 50.L003: st %r1,__LC_SUBCHANNEL_ID
60 st %r1,__LC_SUBCHANNEL_ID
61 lpsw 0 51 lpsw 0
62 sigp 0,0,0(6) 52 sigp 0,0,0(6)
63.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) 53.Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13)
@@ -65,9 +55,6 @@ do_reipl_asm: basr %r13,0
65 .align 8 55 .align 8
66.Lclkcmp: .quad 0x0000000000000000 56.Lclkcmp: .quad 0x0000000000000000
67.Lall: .long 0xff000000 57.Lall: .long 0xff000000
68.Lnull: .long 0x00000000
69.Lctlsave1: .long 0x00000000
70.Lctlsave2: .long 0x00000000
71 .align 8 58 .align 8
72.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 59.Lnewpsw: .long 0x00080000,0x80000000+.Lpg1
73.Lpcnew: .long 0x00080000,0x80000000+.Lecs 60.Lpcnew: .long 0x00080000,0x80000000+.Lecs
diff --git a/arch/s390/kernel/reipl64.S b/arch/s390/kernel/reipl64.S
index de7435054f7c..f18ef260ca23 100644
--- a/arch/s390/kernel/reipl64.S
+++ b/arch/s390/kernel/reipl64.S
@@ -10,10 +10,10 @@
10#include <asm/lowcore.h> 10#include <asm/lowcore.h>
11 .globl do_reipl_asm 11 .globl do_reipl_asm
12do_reipl_asm: basr %r13,0 12do_reipl_asm: basr %r13,0
13.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
14.Lpg1: # do store status of all registers
13 15
14 # do store status of all registers 16 stg %r1,.Lregsave-.Lpg0(%r13)
15
16.Lpg0: stg %r1,.Lregsave-.Lpg0(%r13)
17 lghi %r1,0x1000 17 lghi %r1,0x1000
18 stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1) 18 stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1)
19 lg %r0,.Lregsave-.Lpg0(%r13) 19 lg %r0,.Lregsave-.Lpg0(%r13)
@@ -27,11 +27,7 @@ do_reipl_asm: basr %r13,0
27 stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) 27 stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1)
28 stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) 28 stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1)
29 29
30 lpswe .Lnewpsw-.Lpg0(%r13) 30 lctlg %c6,%c6,.Lall-.Lpg0(%r13)
31.Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13)
32 stctg %c0,%c0,.Lregsave-.Lpg0(%r13)
33 ni .Lregsave+4-.Lpg0(%r13),0xef
34 lctlg %c0,%c0,.Lregsave-.Lpg0(%r13)
35 lgr %r1,%r2 31 lgr %r1,%r2
36 mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13) 32 mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
37 stsch .Lschib-.Lpg0(%r13) 33 stsch .Lschib-.Lpg0(%r13)
@@ -56,8 +52,7 @@ do_reipl_asm: basr %r13,0
56.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3 52.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
57 jz .L003 53 jz .L003
58 bas %r14,.Ldisab-.Lpg0(%r13) 54 bas %r14,.Ldisab-.Lpg0(%r13)
59.L003: spx .Lnull-.Lpg0(%r13) 55.L003: st %r1,__LC_SUBCHANNEL_ID
60 st %r1,__LC_SUBCHANNEL_ID
61 lhi %r1,0 # mode 0 = esa 56 lhi %r1,0 # mode 0 = esa
62 slr %r0,%r0 # set cpuid to zero 57 slr %r0,%r0 # set cpuid to zero
63 sigp %r1,%r0,0x12 # switch to esa mode 58 sigp %r1,%r0,0x12 # switch to esa mode
@@ -70,7 +65,6 @@ do_reipl_asm: basr %r13,0
70.Lclkcmp: .quad 0x0000000000000000 65.Lclkcmp: .quad 0x0000000000000000
71.Lall: .quad 0x00000000ff000000 66.Lall: .quad 0x00000000ff000000
72.Lregsave: .quad 0x0000000000000000 67.Lregsave: .quad 0x0000000000000000
73.Lnull: .long 0x0000000000000000
74 .align 16 68 .align 16
75/* 69/*
76 * These addresses have to be 31 bit otherwise 70 * These addresses have to be 31 bit otherwise
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
index f9899ff2e5b0..3b456b80bcee 100644
--- a/arch/s390/kernel/relocate_kernel.S
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -26,8 +26,7 @@
26 relocate_kernel: 26 relocate_kernel:
27 basr %r13,0 # base address 27 basr %r13,0 # base address
28 .base: 28 .base:
29 stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQ (external) 29 stnsm sys_msk-.base(%r13),0xfb # disable DAT
30 spx zero64-.base(%r13) # absolute addressing mode
31 stctl %c0,%c15,ctlregs-.base(%r13) 30 stctl %c0,%c15,ctlregs-.base(%r13)
32 stm %r0,%r15,gprregs-.base(%r13) 31 stm %r0,%r15,gprregs-.base(%r13)
33 la %r1,load_psw-.base(%r13) 32 la %r1,load_psw-.base(%r13)
@@ -97,8 +96,6 @@
97 lpsw 0 # hopefully start new kernel... 96 lpsw 0 # hopefully start new kernel...
98 97
99 .align 8 98 .align 8
100 zero64:
101 .quad 0
102 load_psw: 99 load_psw:
103 .long 0x00080000,0x80000000 100 .long 0x00080000,0x80000000
104 sys_msk: 101 sys_msk:
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
index 4fb443042d9c..1f9ea2067b59 100644
--- a/arch/s390/kernel/relocate_kernel64.S
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -27,8 +27,7 @@
27 relocate_kernel: 27 relocate_kernel:
28 basr %r13,0 # base address 28 basr %r13,0 # base address
29 .base: 29 .base:
30 stnsm sys_msk-.base(%r13),0xf8 # disable DAT and IRQs 30 stnsm sys_msk-.base(%r13),0xfb # disable DAT
31 spx zero64-.base(%r13) # absolute addressing mode
32 stctg %c0,%c15,ctlregs-.base(%r13) 31 stctg %c0,%c15,ctlregs-.base(%r13)
33 stmg %r0,%r15,gprregs-.base(%r13) 32 stmg %r0,%r15,gprregs-.base(%r13)
34 lghi %r0,3 33 lghi %r0,3
@@ -100,8 +99,6 @@
100 lpsw 0 # hopefully start new kernel... 99 lpsw 0 # hopefully start new kernel...
101 100
102 .align 8 101 .align 8
103 zero64:
104 .quad 0
105 load_psw: 102 load_psw:
106 .long 0x00080000,0x80000000 103 .long 0x00080000,0x80000000
107 sys_msk: 104 sys_msk:
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
new file mode 100644
index 000000000000..be8688c0665c
--- /dev/null
+++ b/arch/s390/kernel/reset.S
@@ -0,0 +1,48 @@
1/*
2 * arch/s390/kernel/reset.S
3 *
4 * Copyright (C) IBM Corp. 2006
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
7
8#include <asm/ptrace.h>
9#include <asm/lowcore.h>
10
11#ifdef CONFIG_64BIT
12
13 .globl reset_mcck_handler
14reset_mcck_handler:
15 basr %r13,0
160: lg %r15,__LC_PANIC_STACK # load panic stack
17 aghi %r15,-STACK_FRAME_OVERHEAD
18 lg %r1,s390_reset_mcck_handler-0b(%r13)
19 ltgr %r1,%r1
20 jz 1f
21 basr %r14,%r1
221: la %r1,4095
23 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
24 lpswe __LC_MCK_OLD_PSW
25
26 .globl s390_reset_mcck_handler
27s390_reset_mcck_handler:
28 .quad 0
29
30#else /* CONFIG_64BIT */
31
32 .globl reset_mcck_handler
33reset_mcck_handler:
34 basr %r13,0
350: l %r15,__LC_PANIC_STACK # load panic stack
36 ahi %r15,-STACK_FRAME_OVERHEAD
37 l %r1,s390_reset_mcck_handler-0b(%r13)
38 ltr %r1,%r1
39 jz 1f
40 basr %r14,%r1
411: lm %r0,%r15,__LC_GPREGS_SAVE_AREA
42 lpsw __LC_MCK_OLD_PSW
43
44 .globl s390_reset_mcck_handler
45s390_reset_mcck_handler:
46 .long 0
47
48#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2aa13e8e000a..b928fecdc743 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -62,13 +62,9 @@ EXPORT_SYMBOL_GPL(uaccess);
62unsigned int console_mode = 0; 62unsigned int console_mode = 0;
63unsigned int console_devno = -1; 63unsigned int console_devno = -1;
64unsigned int console_irq = -1; 64unsigned int console_irq = -1;
65unsigned long memory_size = 0;
66unsigned long machine_flags = 0; 65unsigned long machine_flags = 0;
67struct { 66
68 unsigned long addr, size, type; 67struct mem_chunk memory_chunk[MEMORY_CHUNKS];
69} memory_chunk[MEMORY_CHUNKS] = { { 0 } };
70#define CHUNK_READ_WRITE 0
71#define CHUNK_READ_ONLY 1
72volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */ 68volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
73unsigned long __initdata zholes_size[MAX_NR_ZONES]; 69unsigned long __initdata zholes_size[MAX_NR_ZONES];
74static unsigned long __initdata memory_end; 70static unsigned long __initdata memory_end;
@@ -229,11 +225,11 @@ static void __init conmode_default(void)
229 char *ptr; 225 char *ptr;
230 226
231 if (MACHINE_IS_VM) { 227 if (MACHINE_IS_VM) {
232 __cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL); 228 cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
233 console_devno = simple_strtoul(query_buffer + 5, NULL, 16); 229 console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
234 ptr = strstr(query_buffer, "SUBCHANNEL ="); 230 ptr = strstr(query_buffer, "SUBCHANNEL =");
235 console_irq = simple_strtoul(ptr + 13, NULL, 16); 231 console_irq = simple_strtoul(ptr + 13, NULL, 16);
236 __cpcmd("QUERY TERM", query_buffer, 1024, NULL); 232 cpcmd("QUERY TERM", query_buffer, 1024, NULL);
237 ptr = strstr(query_buffer, "CONMODE"); 233 ptr = strstr(query_buffer, "CONMODE");
238 /* 234 /*
239 * Set the conmode to 3215 so that the device recognition 235 * Set the conmode to 3215 so that the device recognition
@@ -242,7 +238,7 @@ static void __init conmode_default(void)
242 * 3215 and the 3270 driver will try to access the console 238 * 3215 and the 3270 driver will try to access the console
243 * device (3215 as console and 3270 as normal tty). 239 * device (3215 as console and 3270 as normal tty).
244 */ 240 */
245 __cpcmd("TERM CONMODE 3215", NULL, 0, NULL); 241 cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
246 if (ptr == NULL) { 242 if (ptr == NULL) {
247#if defined(CONFIG_SCLP_CONSOLE) 243#if defined(CONFIG_SCLP_CONSOLE)
248 SET_CONSOLE_SCLP; 244 SET_CONSOLE_SCLP;
@@ -299,14 +295,14 @@ static void do_machine_restart_nonsmp(char * __unused)
299static void do_machine_halt_nonsmp(void) 295static void do_machine_halt_nonsmp(void)
300{ 296{
301 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) 297 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
302 cpcmd(vmhalt_cmd, NULL, 0, NULL); 298 __cpcmd(vmhalt_cmd, NULL, 0, NULL);
303 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 299 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
304} 300}
305 301
306static void do_machine_power_off_nonsmp(void) 302static void do_machine_power_off_nonsmp(void)
307{ 303{
308 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) 304 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
309 cpcmd(vmpoff_cmd, NULL, 0, NULL); 305 __cpcmd(vmpoff_cmd, NULL, 0, NULL);
310 signal_processor(smp_processor_id(), sigp_stop_and_store_status); 306 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
311} 307}
312 308
@@ -489,6 +485,37 @@ setup_resources(void)
489 } 485 }
490} 486}
491 487
488static void __init setup_memory_end(void)
489{
490 unsigned long real_size, memory_size;
491 unsigned long max_mem, max_phys;
492 int i;
493
494 memory_size = real_size = 0;
495 max_phys = VMALLOC_END - VMALLOC_MIN_SIZE;
496 memory_end &= PAGE_MASK;
497
498 max_mem = memory_end ? min(max_phys, memory_end) : max_phys;
499
500 for (i = 0; i < MEMORY_CHUNKS; i++) {
501 struct mem_chunk *chunk = &memory_chunk[i];
502
503 real_size = max(real_size, chunk->addr + chunk->size);
504 if (chunk->addr >= max_mem) {
505 memset(chunk, 0, sizeof(*chunk));
506 continue;
507 }
508 if (chunk->addr + chunk->size > max_mem)
509 chunk->size = max_mem - chunk->addr;
510 memory_size = max(memory_size, chunk->addr + chunk->size);
511 }
512 if (!memory_end)
513 memory_end = memory_size;
514 if (real_size > memory_end)
515 printk("More memory detected than supported. Unused: %luk\n",
516 (real_size - memory_end) >> 10);
517}
518
492static void __init 519static void __init
493setup_memory(void) 520setup_memory(void)
494{ 521{
@@ -645,8 +672,6 @@ setup_arch(char **cmdline_p)
645 init_mm.end_data = (unsigned long) &_edata; 672 init_mm.end_data = (unsigned long) &_edata;
646 init_mm.brk = (unsigned long) &_end; 673 init_mm.brk = (unsigned long) &_end;
647 674
648 memory_end = memory_size;
649
650 if (MACHINE_HAS_MVCOS) 675 if (MACHINE_HAS_MVCOS)
651 memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess)); 676 memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess));
652 else 677 else
@@ -654,20 +679,7 @@ setup_arch(char **cmdline_p)
654 679
655 parse_early_param(); 680 parse_early_param();
656 681
657#ifndef CONFIG_64BIT 682 setup_memory_end();
658 memory_end &= ~0x400000UL;
659
660 /*
661 * We need some free virtual space to be able to do vmalloc.
662 * On a machine with 2GB memory we make sure that we have at
663 * least 128 MB free space for vmalloc.
664 */
665 if (memory_end > 1920*1024*1024)
666 memory_end = 1920*1024*1024;
667#else /* CONFIG_64BIT */
668 memory_end &= ~0x200000UL;
669#endif /* CONFIG_64BIT */
670
671 setup_memory(); 683 setup_memory();
672 setup_resources(); 684 setup_resources();
673 setup_lowcore(); 685 setup_lowcore();
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 62822245f9be..19090f7d4f51 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -230,18 +230,37 @@ static inline void do_store_status(void)
230 } 230 }
231} 231}
232 232
233static inline void do_wait_for_stop(void)
234{
235 int cpu;
236
237 /* Wait for all other cpus to enter stopped state */
238 for_each_online_cpu(cpu) {
239 if (cpu == smp_processor_id())
240 continue;
241 while(!smp_cpu_not_running(cpu))
242 cpu_relax();
243 }
244}
245
233/* 246/*
234 * this function sends a 'stop' sigp to all other CPUs in the system. 247 * this function sends a 'stop' sigp to all other CPUs in the system.
235 * it goes straight through. 248 * it goes straight through.
236 */ 249 */
237void smp_send_stop(void) 250void smp_send_stop(void)
238{ 251{
252 /* Disable all interrupts/machine checks */
253 __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
254
239 /* write magic number to zero page (absolute 0) */ 255 /* write magic number to zero page (absolute 0) */
240 lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC; 256 lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
241 257
242 /* stop other processors. */ 258 /* stop other processors. */
243 do_send_stop(); 259 do_send_stop();
244 260
261 /* wait until other processors are stopped */
262 do_wait_for_stop();
263
245 /* store status of other processors. */ 264 /* store status of other processors. */
246 do_store_status(); 265 do_store_status();
247} 266}
@@ -250,88 +269,28 @@ void smp_send_stop(void)
250 * Reboot, halt and power_off routines for SMP. 269 * Reboot, halt and power_off routines for SMP.
251 */ 270 */
252 271
253static void do_machine_restart(void * __unused)
254{
255 int cpu;
256 static atomic_t cpuid = ATOMIC_INIT(-1);
257
258 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
259 signal_processor(smp_processor_id(), sigp_stop);
260
261 /* Wait for all other cpus to enter stopped state */
262 for_each_online_cpu(cpu) {
263 if (cpu == smp_processor_id())
264 continue;
265 while(!smp_cpu_not_running(cpu))
266 cpu_relax();
267 }
268
269 /* Store status of other cpus. */
270 do_store_status();
271
272 /*
273 * Finally call reipl. Because we waited for all other
274 * cpus to enter this function we know that they do
275 * not hold any s390irq-locks (the cpus have been
276 * interrupted by an external interrupt and s390irq
277 * locks are always held disabled).
278 */
279 do_reipl();
280}
281
282void machine_restart_smp(char * __unused) 272void machine_restart_smp(char * __unused)
283{ 273{
284 on_each_cpu(do_machine_restart, NULL, 0, 0); 274 smp_send_stop();
285} 275 do_reipl();
286
287static void do_wait_for_stop(void)
288{
289 unsigned long cr[16];
290
291 __ctl_store(cr, 0, 15);
292 cr[0] &= ~0xffff;
293 cr[6] = 0;
294 __ctl_load(cr, 0, 15);
295 for (;;)
296 enabled_wait();
297}
298
299static void do_machine_halt(void * __unused)
300{
301 static atomic_t cpuid = ATOMIC_INIT(-1);
302
303 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
304 smp_send_stop();
305 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
306 cpcmd(vmhalt_cmd, NULL, 0, NULL);
307 signal_processor(smp_processor_id(),
308 sigp_stop_and_store_status);
309 }
310 do_wait_for_stop();
311} 276}
312 277
313void machine_halt_smp(void) 278void machine_halt_smp(void)
314{ 279{
315 on_each_cpu(do_machine_halt, NULL, 0, 0); 280 smp_send_stop();
316} 281 if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
317 282 __cpcmd(vmhalt_cmd, NULL, 0, NULL);
318static void do_machine_power_off(void * __unused) 283 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
319{ 284 for (;;);
320 static atomic_t cpuid = ATOMIC_INIT(-1);
321
322 if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
323 smp_send_stop();
324 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
325 cpcmd(vmpoff_cmd, NULL, 0, NULL);
326 signal_processor(smp_processor_id(),
327 sigp_stop_and_store_status);
328 }
329 do_wait_for_stop();
330} 285}
331 286
332void machine_power_off_smp(void) 287void machine_power_off_smp(void)
333{ 288{
334 on_each_cpu(do_machine_power_off, NULL, 0, 0); 289 smp_send_stop();
290 if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
291 __cpcmd(vmpoff_cmd, NULL, 0, NULL);
292 signal_processor(smp_processor_id(), sigp_stop_and_store_status);
293 for (;;);
335} 294}
336 295
337/* 296/*
@@ -501,8 +460,6 @@ __init smp_count_cpus(void)
501 */ 460 */
502extern void init_cpu_timer(void); 461extern void init_cpu_timer(void);
503extern void init_cpu_vtimer(void); 462extern void init_cpu_vtimer(void);
504extern int pfault_init(void);
505extern void pfault_fini(void);
506 463
507int __devinit start_secondary(void *cpuvoid) 464int __devinit start_secondary(void *cpuvoid)
508{ 465{
@@ -514,11 +471,9 @@ int __devinit start_secondary(void *cpuvoid)
514#ifdef CONFIG_VIRT_TIMER 471#ifdef CONFIG_VIRT_TIMER
515 init_cpu_vtimer(); 472 init_cpu_vtimer();
516#endif 473#endif
517#ifdef CONFIG_PFAULT
518 /* Enable pfault pseudo page faults on this cpu. */ 474 /* Enable pfault pseudo page faults on this cpu. */
519 if (MACHINE_IS_VM) 475 pfault_init();
520 pfault_init(); 476
521#endif
522 /* Mark this cpu as online */ 477 /* Mark this cpu as online */
523 cpu_set(smp_processor_id(), cpu_online_map); 478 cpu_set(smp_processor_id(), cpu_online_map);
524 /* Switch on interrupts */ 479 /* Switch on interrupts */
@@ -708,11 +663,8 @@ __cpu_disable(void)
708 } 663 }
709 cpu_clear(cpu, cpu_online_map); 664 cpu_clear(cpu, cpu_online_map);
710 665
711#ifdef CONFIG_PFAULT
712 /* Disable pfault pseudo page faults on this cpu. */ 666 /* Disable pfault pseudo page faults on this cpu. */
713 if (MACHINE_IS_VM) 667 pfault_fini();
714 pfault_fini();
715#endif
716 668
717 memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals)); 669 memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
718 memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals)); 670 memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
@@ -860,4 +812,3 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
860EXPORT_SYMBOL(smp_call_function); 812EXPORT_SYMBOL(smp_call_function);
861EXPORT_SYMBOL(smp_get_cpu); 813EXPORT_SYMBOL(smp_get_cpu);
862EXPORT_SYMBOL(smp_put_cpu); 814EXPORT_SYMBOL(smp_put_cpu);
863
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 92ecffbc8d82..3cbb0dcf1f1d 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -58,12 +58,6 @@ int sysctl_userprocess_debug = 0;
58 58
59extern pgm_check_handler_t do_protection_exception; 59extern pgm_check_handler_t do_protection_exception;
60extern pgm_check_handler_t do_dat_exception; 60extern pgm_check_handler_t do_dat_exception;
61#ifdef CONFIG_PFAULT
62extern int pfault_init(void);
63extern void pfault_fini(void);
64extern void pfault_interrupt(__u16 error_code);
65static ext_int_info_t ext_int_pfault;
66#endif
67extern pgm_check_handler_t do_monitor_call; 61extern pgm_check_handler_t do_monitor_call;
68 62
69#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) 63#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
@@ -135,7 +129,7 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high)
135 } 129 }
136} 130}
137 131
138void show_trace(struct task_struct *task, unsigned long * stack) 132void show_trace(struct task_struct *task, unsigned long *stack)
139{ 133{
140 register unsigned long __r15 asm ("15"); 134 register unsigned long __r15 asm ("15");
141 unsigned long sp; 135 unsigned long sp;
@@ -157,6 +151,9 @@ void show_trace(struct task_struct *task, unsigned long * stack)
157 __show_trace(sp, S390_lowcore.thread_info, 151 __show_trace(sp, S390_lowcore.thread_info,
158 S390_lowcore.thread_info + THREAD_SIZE); 152 S390_lowcore.thread_info + THREAD_SIZE);
159 printk("\n"); 153 printk("\n");
154 if (!task)
155 task = current;
156 debug_show_held_locks(task);
160} 157}
161 158
162void show_stack(struct task_struct *task, unsigned long *sp) 159void show_stack(struct task_struct *task, unsigned long *sp)
@@ -739,22 +736,5 @@ void __init trap_init(void)
739 pgm_check_table[0x1C] = &space_switch_exception; 736 pgm_check_table[0x1C] = &space_switch_exception;
740 pgm_check_table[0x1D] = &hfp_sqrt_exception; 737 pgm_check_table[0x1D] = &hfp_sqrt_exception;
741 pgm_check_table[0x40] = &do_monitor_call; 738 pgm_check_table[0x40] = &do_monitor_call;
742 739 pfault_irq_init();
743 if (MACHINE_IS_VM) {
744#ifdef CONFIG_PFAULT
745 /*
746 * Try to get pfault pseudo page faults going.
747 */
748 if (register_early_external_interrupt(0x2603, pfault_interrupt,
749 &ext_int_pfault) != 0)
750 panic("Couldn't request external interrupt 0x2603");
751
752 if (pfault_init() == 0)
753 return;
754
755 /* Tough luck, no pfault. */
756 unregister_early_external_interrupt(0x2603, pfault_interrupt,
757 &ext_int_pfault);
758#endif
759 }
760} 740}