aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/acpi/cstate.c1
-rw-r--r--arch/i386/kernel/alternative.c1
-rw-r--r--arch/i386/kernel/cpu/mcheck/therm_throt.c1
-rw-r--r--arch/m68knommu/Kconfig12
-rw-r--r--arch/m68knommu/kernel/process.c34
-rw-r--r--arch/m68knommu/kernel/setup.c3
-rw-r--r--arch/m68knommu/kernel/sys_m68k.c23
-rw-r--r--arch/m68knommu/kernel/traps.c13
-rw-r--r--arch/m68knommu/platform/5307/head.S20
-rw-r--r--arch/m68knommu/platform/68360/head-ram.S3
-rw-r--r--arch/s390/Kconfig5
-rw-r--r--arch/s390/Makefile3
-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
-rw-r--r--arch/s390/lib/Makefile2
-rw-r--r--arch/s390/lib/uaccess_mvcos.c27
-rw-r--r--arch/s390/lib/uaccess_pt.c153
-rw-r--r--arch/s390/lib/uaccess_std.c67
-rw-r--r--arch/s390/mm/extmem.c38
-rw-r--r--arch/s390/mm/fault.c28
33 files changed, 651 insertions, 416 deletions
diff --git a/arch/i386/kernel/acpi/cstate.c b/arch/i386/kernel/acpi/cstate.c
index 20563e52c622..4664b55f623e 100644
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -11,6 +11,7 @@
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/acpi.h> 12#include <linux/acpi.h>
13#include <linux/cpu.h> 13#include <linux/cpu.h>
14#include <linux/sched.h>
14 15
15#include <acpi/processor.h> 16#include <acpi/processor.h>
16#include <asm/acpi.h> 17#include <asm/acpi.h>
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c
index 583c238e17fb..535f9794fba1 100644
--- a/arch/i386/kernel/alternative.c
+++ b/arch/i386/kernel/alternative.c
@@ -1,4 +1,5 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/sched.h>
2#include <linux/spinlock.h> 3#include <linux/spinlock.h>
3#include <linux/list.h> 4#include <linux/list.h>
4#include <asm/alternative.h> 5#include <asm/alternative.h>
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c
index 2d8703b7ce65..bad8b4420709 100644
--- a/arch/i386/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c
@@ -20,6 +20,7 @@
20#include <linux/cpu.h> 20#include <linux/cpu.h>
21#include <asm/cpu.h> 21#include <asm/cpu.h>
22#include <linux/notifier.h> 22#include <linux/notifier.h>
23#include <linux/jiffies.h>
23#include <asm/therm_throt.h> 24#include <asm/therm_throt.h>
24 25
25/* How long to wait between reporting thermal events */ 26/* How long to wait between reporting thermal events */
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index c1bc22c6d0d8..aa70dde54228 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -173,7 +173,7 @@ config CLOCK_DIV
173 On many SoC style CPUs the master CPU clock is also used to drive 173 On many SoC style CPUs the master CPU clock is also used to drive
174 on-chip peripherals. The clock that is distributed to these 174 on-chip peripherals. The clock that is distributed to these
175 peripherals is sometimes a fixed ratio of the master clock 175 peripherals is sometimes a fixed ratio of the master clock
176 frequency. If so then set this to the divider ration of the 176 frequency. If so then set this to the divider ratio of the
177 master clock to the peripheral clock. If not sure then select 1. 177 master clock to the peripheral clock. If not sure then select 1.
178 178
179config OLDMASK 179config OLDMASK
@@ -192,7 +192,7 @@ config PILOT3
192 Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII. 192 Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
193 193
194config XCOPILOT_BUGS 194config XCOPILOT_BUGS
195 bool " (X)Copilot support" 195 bool "(X)Copilot support"
196 depends on PILOT3 196 depends on PILOT3
197 help 197 help
198 Support the bugs of Xcopilot. 198 Support the bugs of Xcopilot.
@@ -216,20 +216,20 @@ config DRAGEN2
216 Support for the DragenEngine II board. 216 Support for the DragenEngine II board.
217 217
218config DIRECT_IO_ACCESS 218config DIRECT_IO_ACCESS
219 bool " Allow user to access IO directly" 219 bool "Allow user to access IO directly"
220 depends on (UCSIMM || UCDIMM || DRAGEN2) 220 depends on (UCSIMM || UCDIMM || DRAGEN2)
221 help 221 help
222 Disable the CPU internal registers protection in user mode, 222 Disable the CPU internal registers protection in user mode,
223 to allow a user application to read/write them. 223 to allow a user application to read/write them.
224 224
225config INIT_LCD 225config INIT_LCD
226 bool " Initialize LCD" 226 bool "Initialize LCD"
227 depends on (UCSIMM || UCDIMM || DRAGEN2) 227 depends on (UCSIMM || UCDIMM || DRAGEN2)
228 help 228 help
229 Initialize the LCD controller of the 68x328 processor. 229 Initialize the LCD controller of the 68x328 processor.
230 230
231config MEMORY_RESERVE 231config MEMORY_RESERVE
232 int " Memory reservation (MiB)" 232 int "Memory reservation (MiB)"
233 depends on (UCSIMM || UCDIMM) 233 depends on (UCSIMM || UCDIMM)
234 help 234 help
235 Reserve certain memory regions on 68x328 based boards. 235 Reserve certain memory regions on 68x328 based boards.
@@ -409,7 +409,7 @@ config MOD5272
409 Support for the Netburner MOD-5272 board. 409 Support for the Netburner MOD-5272 board.
410 410
411config ROMFS_FROM_ROM 411config ROMFS_FROM_ROM
412 bool " ROMFS image not RAM resident" 412 bool "ROMFS image not RAM resident"
413 depends on (NETtel || SNAPGEAR) 413 depends on (NETtel || SNAPGEAR)
414 help 414 help
415 The ROMfs filesystem will stay resident in the FLASH/ROM, not be 415 The ROMfs filesystem will stay resident in the FLASH/ROM, not be
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index c18a83306953..941955dc3b7c 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -290,7 +290,7 @@ void dump(struct pt_regs *fp)
290 unsigned char *tp; 290 unsigned char *tp;
291 int i; 291 int i;
292 292
293 printk(KERN_EMERG "\nCURRENT PROCESS:\n\n"); 293 printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n");
294 printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid); 294 printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
295 295
296 if (current->mm) { 296 if (current->mm) {
@@ -301,7 +301,8 @@ void dump(struct pt_regs *fp)
301 (int) current->mm->end_data, 301 (int) current->mm->end_data,
302 (int) current->mm->end_data, 302 (int) current->mm->end_data,
303 (int) current->mm->brk); 303 (int) current->mm->brk);
304 printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n", 304 printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n"
305 KERN_EMERG "\n",
305 (int) current->mm->start_stack, 306 (int) current->mm->start_stack,
306 (int)(((unsigned long) current) + THREAD_SIZE)); 307 (int)(((unsigned long) current) + THREAD_SIZE));
307 } 308 }
@@ -312,36 +313,35 @@ void dump(struct pt_regs *fp)
312 fp->d0, fp->d1, fp->d2, fp->d3); 313 fp->d0, fp->d1, fp->d2, fp->d3);
313 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 314 printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
314 fp->d4, fp->d5, fp->a0, fp->a1); 315 fp->d4, fp->d5, fp->a0, fp->a1);
315 printk(KERN_EMERG "\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(), 316 printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x TRAPFRAME: %08x\n",
316 (unsigned int) fp); 317 (unsigned int) rdusp(), (unsigned int) fp);
317 318
318 printk(KERN_EMERG "\nCODE:"); 319 printk(KERN_EMERG "\n" KERN_EMERG "CODE:");
319 tp = ((unsigned char *) fp->pc) - 0x20; 320 tp = ((unsigned char *) fp->pc) - 0x20;
320 for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { 321 for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
321 if ((i % 0x10) == 0) 322 if ((i % 0x10) == 0)
322 printk(KERN_EMERG "\n%08x: ", (int) (tp + i)); 323 printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
323 printk(KERN_EMERG "%08x ", (int) *sp++); 324 printk("%08x ", (int) *sp++);
324 } 325 }
325 printk(KERN_EMERG "\n"); 326 printk("\n" KERN_EMERG "\n");
326 327
327 printk(KERN_EMERG "\nKERNEL STACK:"); 328 printk(KERN_EMERG "KERNEL STACK:");
328 tp = ((unsigned char *) fp) - 0x40; 329 tp = ((unsigned char *) fp) - 0x40;
329 for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { 330 for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
330 if ((i % 0x10) == 0) 331 if ((i % 0x10) == 0)
331 printk(KERN_EMERG "\n%08x: ", (int) (tp + i)); 332 printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
332 printk(KERN_EMERG "%08x ", (int) *sp++); 333 printk("%08x ", (int) *sp++);
333 } 334 }
334 printk(KERN_EMERG "\n"); 335 printk("\n" KERN_EMERG "\n");
335 printk(KERN_EMERG "\n");
336 336
337 printk(KERN_EMERG "\nUSER STACK:"); 337 printk(KERN_EMERG "USER STACK:");
338 tp = (unsigned char *) (rdusp() - 0x10); 338 tp = (unsigned char *) (rdusp() - 0x10);
339 for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { 339 for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
340 if ((i % 0x10) == 0) 340 if ((i % 0x10) == 0)
341 printk(KERN_EMERG "\n%08x: ", (int) (tp + i)); 341 printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
342 printk(KERN_EMERG "%08x ", (int) *sp++); 342 printk("%08x ", (int) *sp++);
343 } 343 }
344 printk(KERN_EMERG "\n\n"); 344 printk("\n" KERN_EMERG "\n");
345} 345}
346 346
347/* 347/*
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 7b21959eaeae..9cf2e4d1fc77 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -36,10 +36,7 @@
36#include <asm/setup.h> 36#include <asm/setup.h>
37#include <asm/irq.h> 37#include <asm/irq.h>
38#include <asm/machdep.h> 38#include <asm/machdep.h>
39
40#ifdef CONFIG_BLK_DEV_INITRD
41#include <asm/pgtable.h> 39#include <asm/pgtable.h>
42#endif
43 40
44unsigned long memory_start; 41unsigned long memory_start;
45unsigned long memory_end; 42unsigned long memory_end;
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c
index c3494b8447d1..3265b2d734db 100644
--- a/arch/m68knommu/kernel/sys_m68k.c
+++ b/arch/m68knommu/kernel/sys_m68k.c
@@ -137,7 +137,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
137asmlinkage int sys_ipc (uint call, int first, int second, 137asmlinkage int sys_ipc (uint call, int first, int second,
138 int third, void *ptr, long fifth) 138 int third, void *ptr, long fifth)
139{ 139{
140 int version; 140 int version, ret;
141 141
142 version = call >> 16; /* hack for backward compatibility */ 142 version = call >> 16; /* hack for backward compatibility */
143 call &= 0xffff; 143 call &= 0xffff;
@@ -190,6 +190,27 @@ asmlinkage int sys_ipc (uint call, int first, int second,
190 default: 190 default:
191 return -EINVAL; 191 return -EINVAL;
192 } 192 }
193 if (call <= SHMCTL)
194 switch (call) {
195 case SHMAT:
196 switch (version) {
197 default: {
198 ulong raddr;
199 ret = do_shmat (first, ptr, second, &raddr);
200 if (ret)
201 return ret;
202 return put_user (raddr, (ulong __user *) third);
203 }
204 }
205 case SHMDT:
206 return sys_shmdt (ptr);
207 case SHMGET:
208 return sys_shmget (first, second, third);
209 case SHMCTL:
210 return sys_shmctl (first, second, ptr);
211 default:
212 return -ENOSYS;
213 }
193 214
194 return -EINVAL; 215 return -EINVAL;
195} 216}
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index 17649d2543ef..9129b3a5258b 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -127,11 +127,12 @@ void show_stack(struct task_struct *task, unsigned long *stack)
127 if (stack + 1 > endstack) 127 if (stack + 1 > endstack)
128 break; 128 break;
129 if (i % 8 == 0) 129 if (i % 8 == 0)
130 printk(KERN_EMERG "\n "); 130 printk("\n" KERN_EMERG " ");
131 printk(KERN_EMERG " %08lx", *stack++); 131 printk(" %08lx", *stack++);
132 } 132 }
133 printk("\n");
133 134
134 printk(KERN_EMERG "\nCall Trace:"); 135 printk(KERN_EMERG "Call Trace:");
135 i = 0; 136 i = 0;
136 while (stack + 1 <= endstack) { 137 while (stack + 1 <= endstack) {
137 addr = *stack++; 138 addr = *stack++;
@@ -146,12 +147,12 @@ void show_stack(struct task_struct *task, unsigned long *stack)
146 if (((addr >= (unsigned long) &_start) && 147 if (((addr >= (unsigned long) &_start) &&
147 (addr <= (unsigned long) &_etext))) { 148 (addr <= (unsigned long) &_etext))) {
148 if (i % 4 == 0) 149 if (i % 4 == 0)
149 printk(KERN_EMERG "\n "); 150 printk("\n" KERN_EMERG " ");
150 printk(KERN_EMERG " [<%08lx>]", addr); 151 printk(" [<%08lx>]", addr);
151 i++; 152 i++;
152 } 153 }
153 } 154 }
154 printk(KERN_EMERG "\n"); 155 printk("\n");
155} 156}
156 157
157void bad_super_trap(struct frame *fp) 158void bad_super_trap(struct frame *fp)
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index f2edb6498cd9..b9aa0ca29bfb 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -64,6 +64,26 @@
64 negl %d0 /* negate bits */ 64 negl %d0 /* negate bits */
65.endm 65.endm
66 66
67#elif defined(CONFIG_M520x)
68.macro GET_MEM_SIZE
69 clrl %d0
70 movel MCF_MBAR+MCFSIM_SDCS0, %d2 /* Get SDRAM chip select 0 config */
71 andl #0x1f, %d2 /* Get only the chip select size */
72 beq 3f /* Check if it is enabled */
73 addql #1, %d2 /* Form exponent */
74 moveql #1, %d0
75 lsll %d2, %d0 /* 2 ^ exponent */
763:
77 movel MCF_MBAR+MCFSIM_SDCS1, %d2 /* Get SDRAM chip select 1 config */
78 andl #0x1f, %d2 /* Get only the chip select size */
79 beq 4f /* Check if it is enabled */
80 addql #1, %d2 /* Form exponent */
81 moveql #1, %d1
82 lsll %d2, %d1 /* 2 ^ exponent */
83 addl %d1, %d0 /* Total size of SDRAM in d0 */
844:
85.endm
86
67#else 87#else
68#error "ERROR: I don't know how to probe your boards memory size?" 88#error "ERROR: I don't know how to probe your boards memory size?"
69#endif 89#endif
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
index 2ea51479f13a..2ef06242398b 100644
--- a/arch/m68knommu/platform/68360/head-ram.S
+++ b/arch/m68knommu/platform/68360/head-ram.S
@@ -25,6 +25,7 @@
25.global _periph_base 25.global _periph_base
26 26
27#define RAMEND (CONFIG_RAMBASE + CONFIG_RAMSIZE) 27#define RAMEND (CONFIG_RAMBASE + CONFIG_RAMSIZE)
28#define ROMEND (CONFIG_ROMBASE + CONFIG_ROMSIZE)
28 29
29#define REGB 0x1000 30#define REGB 0x1000
30#define PEPAR (_dprbase + REGB + 0x0016) 31#define PEPAR (_dprbase + REGB + 0x0016)
@@ -175,7 +176,7 @@ configure_chip_select_0:
175 move.l %d0, BR0 176 move.l %d0, BR0
176 177
177configure_chip_select_1: 178configure_chip_select_1:
178 move.l #__rom_end, %d0 179 move.l #ROMEND, %d0
179 subi.l #__rom_start, %d0 180 subi.l #__rom_start, %d0
180 subq.l #0x01, %d0 181 subq.l #0x01, %d0
181 eori.l #SIM_OR_MASK, %d0 182 eori.l #SIM_OR_MASK, %d0
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 245b81bc7157..583d9ff0a571 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -33,9 +33,6 @@ config GENERIC_CALIBRATE_DELAY
33config GENERIC_TIME 33config GENERIC_TIME
34 def_bool y 34 def_bool y
35 35
36config GENERIC_BUST_SPINLOCK
37 bool
38
39mainmenu "Linux Kernel Configuration" 36mainmenu "Linux Kernel Configuration"
40 37
41config S390 38config S390
@@ -181,7 +178,7 @@ config PACK_STACK
181 178
182config SMALL_STACK 179config SMALL_STACK
183 bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb" 180 bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb"
184 depends on PACK_STACK 181 depends on PACK_STACK && !LOCKDEP
185 help 182 help
186 If you say Y here and the compiler supports the -mkernel-backchain 183 If you say Y here and the compiler supports the -mkernel-backchain
187 option the kernel will use a smaller kernel stack size. For 31 bit 184 option the kernel will use a smaller kernel stack size. For 31 bit
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 5deb9f7544a1..6598e5268573 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -35,6 +35,9 @@ cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
35cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) 35cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
36cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109) 36cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
37 37
38#KBUILD_IMAGE is necessary for make rpm
39KBUILD_IMAGE :=arch/s390/boot/image
40
38# 41#
39# Prevent tail-call optimizations, to get clearer backtraces: 42# Prevent tail-call optimizations, to get clearer backtraces:
40# 43#
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}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index b0cfa6c4883d..b5f94cf3bde8 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@
4 4
5EXTRA_AFLAGS := -traditional 5EXTRA_AFLAGS := -traditional
6 6
7lib-y += delay.o string.o uaccess_std.o 7lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
8lib-$(CONFIG_32BIT) += div64.o 8lib-$(CONFIG_32BIT) += div64.o
9lib-$(CONFIG_64BIT) += uaccess_mvcos.o 9lib-$(CONFIG_64BIT) += uaccess_mvcos.o
10lib-$(CONFIG_SMP) += spinlock.o 10lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 121b2935a422..f9a23d57eb79 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -27,6 +27,9 @@
27#define SLR "slgr" 27#define SLR "slgr"
28#endif 28#endif
29 29
30extern size_t copy_from_user_std(size_t, const void __user *, void *);
31extern size_t copy_to_user_std(size_t, void __user *, const void *);
32
30size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) 33size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
31{ 34{
32 register unsigned long reg0 asm("0") = 0x81UL; 35 register unsigned long reg0 asm("0") = 0x81UL;
@@ -66,6 +69,13 @@ size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
66 return size; 69 return size;
67} 70}
68 71
72size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
73{
74 if (size <= 256)
75 return copy_from_user_std(size, ptr, x);
76 return copy_from_user_mvcos(size, ptr, x);
77}
78
69size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) 79size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
70{ 80{
71 register unsigned long reg0 asm("0") = 0x810000UL; 81 register unsigned long reg0 asm("0") = 0x810000UL;
@@ -95,6 +105,13 @@ size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
95 return size; 105 return size;
96} 106}
97 107
108size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, const void *x)
109{
110 if (size <= 256)
111 return copy_to_user_std(size, ptr, x);
112 return copy_to_user_mvcos(size, ptr, x);
113}
114
98size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from) 115size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from)
99{ 116{
100 register unsigned long reg0 asm("0") = 0x810081UL; 117 register unsigned long reg0 asm("0") = 0x810081UL;
@@ -145,18 +162,16 @@ size_t clear_user_mvcos(size_t size, void __user *to)
145 return size; 162 return size;
146} 163}
147 164
148extern size_t copy_from_user_std_small(size_t, const void __user *, void *);
149extern size_t copy_to_user_std_small(size_t, void __user *, const void *);
150extern size_t strnlen_user_std(size_t, const char __user *); 165extern size_t strnlen_user_std(size_t, const char __user *);
151extern size_t strncpy_from_user_std(size_t, const char __user *, char *); 166extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
152extern int futex_atomic_op(int, int __user *, int, int *); 167extern int futex_atomic_op(int, int __user *, int, int *);
153extern int futex_atomic_cmpxchg(int __user *, int, int); 168extern int futex_atomic_cmpxchg(int __user *, int, int);
154 169
155struct uaccess_ops uaccess_mvcos = { 170struct uaccess_ops uaccess_mvcos = {
156 .copy_from_user = copy_from_user_mvcos, 171 .copy_from_user = copy_from_user_mvcos_check,
157 .copy_from_user_small = copy_from_user_std_small, 172 .copy_from_user_small = copy_from_user_std,
158 .copy_to_user = copy_to_user_mvcos, 173 .copy_to_user = copy_to_user_mvcos_check,
159 .copy_to_user_small = copy_to_user_std_small, 174 .copy_to_user_small = copy_to_user_std,
160 .copy_in_user = copy_in_user_mvcos, 175 .copy_in_user = copy_in_user_mvcos,
161 .clear_user = clear_user_mvcos, 176 .clear_user = clear_user_mvcos,
162 .strnlen_user = strnlen_user_std, 177 .strnlen_user = strnlen_user_std,
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
new file mode 100644
index 000000000000..8741bdc09299
--- /dev/null
+++ b/arch/s390/lib/uaccess_pt.c
@@ -0,0 +1,153 @@
1/*
2 * arch/s390/lib/uaccess_pt.c
3 *
4 * User access functions based on page table walks.
5 *
6 * Copyright IBM Corp. 2006
7 * Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
8 */
9
10#include <linux/errno.h>
11#include <asm/uaccess.h>
12#include <linux/mm.h>
13#include <asm/futex.h>
14
15static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
16 int write_access)
17{
18 struct vm_area_struct *vma;
19 int ret = -EFAULT;
20
21 down_read(&mm->mmap_sem);
22 vma = find_vma(mm, address);
23 if (unlikely(!vma))
24 goto out;
25 if (unlikely(vma->vm_start > address)) {
26 if (!(vma->vm_flags & VM_GROWSDOWN))
27 goto out;
28 if (expand_stack(vma, address))
29 goto out;
30 }
31
32 if (!write_access) {
33 /* page not present, check vm flags */
34 if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
35 goto out;
36 } else {
37 if (!(vma->vm_flags & VM_WRITE))
38 goto out;
39 }
40
41survive:
42 switch (handle_mm_fault(mm, vma, address, write_access)) {
43 case VM_FAULT_MINOR:
44 current->min_flt++;
45 break;
46 case VM_FAULT_MAJOR:
47 current->maj_flt++;
48 break;
49 case VM_FAULT_SIGBUS:
50 goto out_sigbus;
51 case VM_FAULT_OOM:
52 goto out_of_memory;
53 default:
54 BUG();
55 }
56 ret = 0;
57out:
58 up_read(&mm->mmap_sem);
59 return ret;
60
61out_of_memory:
62 up_read(&mm->mmap_sem);
63 if (current->pid == 1) {
64 yield();
65 goto survive;
66 }
67 printk("VM: killing process %s\n", current->comm);
68 return ret;
69
70out_sigbus:
71 up_read(&mm->mmap_sem);
72 current->thread.prot_addr = address;
73 current->thread.trap_no = 0x11;
74 force_sig(SIGBUS, current);
75 return ret;
76}
77
78static inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
79 size_t n, int write_user)
80{
81 struct mm_struct *mm = current->mm;
82 unsigned long offset, pfn, done, size;
83 pgd_t *pgd;
84 pmd_t *pmd;
85 pte_t *pte;
86 void *from, *to;
87
88 done = 0;
89retry:
90 spin_lock(&mm->page_table_lock);
91 do {
92 pgd = pgd_offset(mm, uaddr);
93 if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
94 goto fault;
95
96 pmd = pmd_offset(pgd, uaddr);
97 if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
98 goto fault;
99
100 pte = pte_offset_map(pmd, uaddr);
101 if (!pte || !pte_present(*pte) ||
102 (write_user && !pte_write(*pte)))
103 goto fault;
104
105 pfn = pte_pfn(*pte);
106 if (!pfn_valid(pfn))
107 goto out;
108
109 offset = uaddr & (PAGE_SIZE - 1);
110 size = min(n - done, PAGE_SIZE - offset);
111 if (write_user) {
112 to = (void *)((pfn << PAGE_SHIFT) + offset);
113 from = kptr + done;
114 } else {
115 from = (void *)((pfn << PAGE_SHIFT) + offset);
116 to = kptr + done;
117 }
118 memcpy(to, from, size);
119 done += size;
120 uaddr += size;
121 } while (done < n);
122out:
123 spin_unlock(&mm->page_table_lock);
124 return n - done;
125fault:
126 spin_unlock(&mm->page_table_lock);
127 if (__handle_fault(mm, uaddr, write_user))
128 return n - done;
129 goto retry;
130}
131
132size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
133{
134 size_t rc;
135
136 if (segment_eq(get_fs(), KERNEL_DS)) {
137 memcpy(to, (void __kernel __force *) from, n);
138 return 0;
139 }
140 rc = __user_copy_pt((unsigned long) from, to, n, 0);
141 if (unlikely(rc))
142 memset(to + n - rc, 0, rc);
143 return rc;
144}
145
146size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
147{
148 if (segment_eq(get_fs(), KERNEL_DS)) {
149 memcpy((void __kernel __force *) to, from, n);
150 return 0;
151 }
152 return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
153}
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index f44f0078b354..2d549ed2e113 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -28,6 +28,9 @@
28#define SLR "slgr" 28#define SLR "slgr"
29#endif 29#endif
30 30
31extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to);
32extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from);
33
31size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) 34size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
32{ 35{
33 unsigned long tmp1, tmp2; 36 unsigned long tmp1, tmp2;
@@ -69,34 +72,11 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
69 return size; 72 return size;
70} 73}
71 74
72size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x) 75size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x)
73{ 76{
74 unsigned long tmp1, tmp2; 77 if (size <= 1024)
75 78 return copy_from_user_std(size, ptr, x);
76 tmp1 = 0UL; 79 return copy_from_user_pt(size, ptr, x);
77 asm volatile(
78 "0: mvcp 0(%0,%2),0(%1),%3\n"
79 " "SLR" %0,%0\n"
80 " j 5f\n"
81 "1: la %4,255(%1)\n" /* %4 = ptr + 255 */
82 " "LHI" %3,-4096\n"
83 " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */
84 " "SLR" %4,%1\n"
85 " "CLR" %0,%4\n" /* copy crosses next page boundary? */
86 " jnh 5f\n"
87 "2: mvcp 0(%4,%2),0(%1),%3\n"
88 " "SLR" %0,%4\n"
89 " "ALR" %2,%4\n"
90 "3:"LHI" %4,-1\n"
91 " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
92 " bras %3,4f\n"
93 " xc 0(1,%2),0(%2)\n"
94 "4: ex %4,0(%3)\n"
95 "5:\n"
96 EX_TABLE(0b,1b) EX_TABLE(2b,3b)
97 : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
98 : : "cc", "memory");
99 return size;
100} 80}
101 81
102size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) 82size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
@@ -130,28 +110,11 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
130 return size; 110 return size;
131} 111}
132 112
133size_t copy_to_user_std_small(size_t size, void __user *ptr, const void *x) 113size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x)
134{ 114{
135 unsigned long tmp1, tmp2; 115 if (size <= 1024)
136 116 return copy_to_user_std(size, ptr, x);
137 tmp1 = 0UL; 117 return copy_to_user_pt(size, ptr, x);
138 asm volatile(
139 "0: mvcs 0(%0,%1),0(%2),%3\n"
140 " "SLR" %0,%0\n"
141 " j 3f\n"
142 "1: la %4,255(%1)\n" /* ptr + 255 */
143 " "LHI" %3,-4096\n"
144 " nr %4,%3\n" /* (ptr + 255) & -4096UL */
145 " "SLR" %4,%1\n"
146 " "CLR" %0,%4\n" /* copy crosses next page boundary? */
147 " jnh 3f\n"
148 "2: mvcs 0(%4,%1),0(%2),%3\n"
149 " "SLR" %0,%4\n"
150 "3:\n"
151 EX_TABLE(0b,1b) EX_TABLE(2b,3b)
152 : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
153 : : "cc", "memory");
154 return size;
155} 118}
156 119
157size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) 120size_t copy_in_user_std(size_t size, void __user *to, const void __user *from)
@@ -343,10 +306,10 @@ int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval)
343} 306}
344 307
345struct uaccess_ops uaccess_std = { 308struct uaccess_ops uaccess_std = {
346 .copy_from_user = copy_from_user_std, 309 .copy_from_user = copy_from_user_std_check,
347 .copy_from_user_small = copy_from_user_std_small, 310 .copy_from_user_small = copy_from_user_std,
348 .copy_to_user = copy_to_user_std, 311 .copy_to_user = copy_to_user_std_check,
349 .copy_to_user_small = copy_to_user_std_small, 312 .copy_to_user_small = copy_to_user_std,
350 .copy_in_user = copy_in_user_std, 313 .copy_in_user = copy_in_user_std,
351 .clear_user = clear_user_std, 314 .clear_user = clear_user_std,
352 .strnlen_user = strnlen_user_std, 315 .strnlen_user = strnlen_user_std,
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 226275d5c4f6..9e9bc48463a5 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -14,12 +14,13 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/bootmem.h> 16#include <linux/bootmem.h>
17#include <linux/ctype.h>
17#include <asm/page.h> 18#include <asm/page.h>
18#include <asm/ebcdic.h> 19#include <asm/ebcdic.h>
19#include <asm/errno.h> 20#include <asm/errno.h>
20#include <asm/extmem.h> 21#include <asm/extmem.h>
21#include <asm/cpcmd.h> 22#include <asm/cpcmd.h>
22#include <linux/ctype.h> 23#include <asm/setup.h>
23 24
24#define DCSS_DEBUG /* Debug messages on/off */ 25#define DCSS_DEBUG /* Debug messages on/off */
25 26
@@ -77,15 +78,11 @@ struct dcss_segment {
77 int segcnt; 78 int segcnt;
78}; 79};
79 80
80static DEFINE_SPINLOCK(dcss_lock); 81static DEFINE_MUTEX(dcss_lock);
81static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list); 82static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list);
82static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC", 83static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
83 "EW/EN-MIXED" }; 84 "EW/EN-MIXED" };
84 85
85extern struct {
86 unsigned long addr, size, type;
87} memory_chunk[MEMORY_CHUNKS];
88
89/* 86/*
90 * Create the 8 bytes, ebcdic VM segment name from 87 * Create the 8 bytes, ebcdic VM segment name from
91 * an ascii name. 88 * an ascii name.
@@ -117,7 +114,7 @@ segment_by_name (char *name)
117 struct list_head *l; 114 struct list_head *l;
118 struct dcss_segment *tmp, *retval = NULL; 115 struct dcss_segment *tmp, *retval = NULL;
119 116
120 assert_spin_locked(&dcss_lock); 117 BUG_ON(!mutex_is_locked(&dcss_lock));
121 dcss_mkname (name, dcss_name); 118 dcss_mkname (name, dcss_name);
122 list_for_each (l, &dcss_list) { 119 list_for_each (l, &dcss_list) {
123 tmp = list_entry (l, struct dcss_segment, list); 120 tmp = list_entry (l, struct dcss_segment, list);
@@ -249,8 +246,8 @@ segment_overlaps_storage(struct dcss_segment *seg)
249{ 246{
250 int i; 247 int i;
251 248
252 for (i=0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { 249 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
253 if (memory_chunk[i].type != 0) 250 if (memory_chunk[i].type != CHUNK_READ_WRITE)
254 continue; 251 continue;
255 if ((memory_chunk[i].addr >> 20) > (seg->end >> 20)) 252 if ((memory_chunk[i].addr >> 20) > (seg->end >> 20))
256 continue; 253 continue;
@@ -272,7 +269,7 @@ segment_overlaps_others (struct dcss_segment *seg)
272 struct list_head *l; 269 struct list_head *l;
273 struct dcss_segment *tmp; 270 struct dcss_segment *tmp;
274 271
275 assert_spin_locked(&dcss_lock); 272 BUG_ON(!mutex_is_locked(&dcss_lock));
276 list_for_each(l, &dcss_list) { 273 list_for_each(l, &dcss_list) {
277 tmp = list_entry(l, struct dcss_segment, list); 274 tmp = list_entry(l, struct dcss_segment, list);
278 if ((tmp->start_addr >> 20) > (seg->end >> 20)) 275 if ((tmp->start_addr >> 20) > (seg->end >> 20))
@@ -429,7 +426,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
429 if (!MACHINE_IS_VM) 426 if (!MACHINE_IS_VM)
430 return -ENOSYS; 427 return -ENOSYS;
431 428
432 spin_lock (&dcss_lock); 429 mutex_lock(&dcss_lock);
433 seg = segment_by_name (name); 430 seg = segment_by_name (name);
434 if (seg == NULL) 431 if (seg == NULL)
435 rc = __segment_load (name, do_nonshared, addr, end); 432 rc = __segment_load (name, do_nonshared, addr, end);
@@ -444,7 +441,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
444 rc = -EPERM; 441 rc = -EPERM;
445 } 442 }
446 } 443 }
447 spin_unlock (&dcss_lock); 444 mutex_unlock(&dcss_lock);
448 return rc; 445 return rc;
449} 446}
450 447
@@ -467,7 +464,7 @@ segment_modify_shared (char *name, int do_nonshared)
467 unsigned long dummy; 464 unsigned long dummy;
468 int dcss_command, rc, diag_cc; 465 int dcss_command, rc, diag_cc;
469 466
470 spin_lock (&dcss_lock); 467 mutex_lock(&dcss_lock);
471 seg = segment_by_name (name); 468 seg = segment_by_name (name);
472 if (seg == NULL) { 469 if (seg == NULL) {
473 rc = -EINVAL; 470 rc = -EINVAL;
@@ -508,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared)
508 &dummy, &dummy); 505 &dummy, &dummy);
509 kfree(seg); 506 kfree(seg);
510 out_unlock: 507 out_unlock:
511 spin_unlock(&dcss_lock); 508 mutex_unlock(&dcss_lock);
512 return rc; 509 return rc;
513} 510}
514 511
@@ -526,7 +523,7 @@ segment_unload(char *name)
526 if (!MACHINE_IS_VM) 523 if (!MACHINE_IS_VM)
527 return; 524 return;
528 525
529 spin_lock(&dcss_lock); 526 mutex_lock(&dcss_lock);
530 seg = segment_by_name (name); 527 seg = segment_by_name (name);
531 if (seg == NULL) { 528 if (seg == NULL) {
532 PRINT_ERR ("could not find segment %s in segment_unload, " 529 PRINT_ERR ("could not find segment %s in segment_unload, "
@@ -540,7 +537,7 @@ segment_unload(char *name)
540 kfree(seg); 537 kfree(seg);
541 } 538 }
542out_unlock: 539out_unlock:
543 spin_unlock(&dcss_lock); 540 mutex_unlock(&dcss_lock);
544} 541}
545 542
546/* 543/*
@@ -559,12 +556,13 @@ segment_save(char *name)
559 if (!MACHINE_IS_VM) 556 if (!MACHINE_IS_VM)
560 return; 557 return;
561 558
562 spin_lock(&dcss_lock); 559 mutex_lock(&dcss_lock);
563 seg = segment_by_name (name); 560 seg = segment_by_name (name);
564 561
565 if (seg == NULL) { 562 if (seg == NULL) {
566 PRINT_ERR ("could not find segment %s in segment_save, please report to linux390@de.ibm.com\n",name); 563 PRINT_ERR("could not find segment %s in segment_save, please "
567 return; 564 "report to linux390@de.ibm.com\n", name);
565 goto out;
568 } 566 }
569 567
570 startpfn = seg->start_addr >> PAGE_SHIFT; 568 startpfn = seg->start_addr >> PAGE_SHIFT;
@@ -591,7 +589,7 @@ segment_save(char *name)
591 goto out; 589 goto out;
592 } 590 }
593out: 591out:
594 spin_unlock(&dcss_lock); 592 mutex_unlock(&dcss_lock);
595} 593}
596 594
597EXPORT_SYMBOL(segment_load); 595EXPORT_SYMBOL(segment_load);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 1c323bbfda91..cd85e34d8703 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -31,6 +31,7 @@
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32#include <asm/pgtable.h> 32#include <asm/pgtable.h>
33#include <asm/kdebug.h> 33#include <asm/kdebug.h>
34#include <asm/s390_ext.h>
34 35
35#ifndef CONFIG_64BIT 36#ifndef CONFIG_64BIT
36#define __FAIL_ADDR_MASK 0x7ffff000 37#define __FAIL_ADDR_MASK 0x7ffff000
@@ -394,6 +395,7 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code)
394/* 395/*
395 * 'pfault' pseudo page faults routines. 396 * 'pfault' pseudo page faults routines.
396 */ 397 */
398static ext_int_info_t ext_int_pfault;
397static int pfault_disable = 0; 399static int pfault_disable = 0;
398 400
399static int __init nopfault(char *str) 401static int __init nopfault(char *str)
@@ -422,7 +424,7 @@ int pfault_init(void)
422 __PF_RES_FIELD }; 424 __PF_RES_FIELD };
423 int rc; 425 int rc;
424 426
425 if (pfault_disable) 427 if (!MACHINE_IS_VM || pfault_disable)
426 return -1; 428 return -1;
427 asm volatile( 429 asm volatile(
428 " diag %1,%0,0x258\n" 430 " diag %1,%0,0x258\n"
@@ -440,7 +442,7 @@ void pfault_fini(void)
440 pfault_refbk_t refbk = 442 pfault_refbk_t refbk =
441 { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL }; 443 { 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL };
442 444
443 if (pfault_disable) 445 if (!MACHINE_IS_VM || pfault_disable)
444 return; 446 return;
445 __ctl_clear_bit(0,9); 447 __ctl_clear_bit(0,9);
446 asm volatile( 448 asm volatile(
@@ -500,5 +502,25 @@ pfault_interrupt(__u16 error_code)
500 set_tsk_need_resched(tsk); 502 set_tsk_need_resched(tsk);
501 } 503 }
502} 504}
503#endif
504 505
506void __init pfault_irq_init(void)
507{
508 if (!MACHINE_IS_VM)
509 return;
510
511 /*
512 * Try to get pfault pseudo page faults going.
513 */
514 if (register_early_external_interrupt(0x2603, pfault_interrupt,
515 &ext_int_pfault) != 0)
516 panic("Couldn't request external interrupt 0x2603");
517
518 if (pfault_init() == 0)
519 return;
520
521 /* Tough luck, no pfault. */
522 pfault_disable = 1;
523 unregister_early_external_interrupt(0x2603, pfault_interrupt,
524 &ext_int_pfault);
525}
526#endif