aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-02-05 15:18:37 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-05 15:18:37 -0500
commitab14de6c37fae22911ba99f4171613e6d758050b (patch)
tree7545169fe9d64a82616ae37f2b6c1a420c77f30f
parent31ee4b2f40994e8b21691f85cdd4052551a789b7 (diff)
[S390] Convert memory detection into C code.
Hopefully this will make it more maintainable and less error prone. Code makes use of search_exception_tables(). Since it calls this function before the kernel exeception table is sorted, there is an early call to sort_main_extable(). This way it's easy to use the already present infrastructure of fixup sections. Also this would allows to easily convert the rest of head[31|64].S into C code. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/defconfig1
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/base.S150
-rw-r--r--arch/s390/kernel/early.c307
-rw-r--r--arch/s390/kernel/head31.S164
-rw-r--r--arch/s390/kernel/head64.S175
-rw-r--r--arch/s390/kernel/ipl.c15
-rw-r--r--arch/s390/kernel/reset.S90
-rw-r--r--arch/s390/kernel/setup.c134
-rw-r--r--drivers/s390/Kconfig8
-rw-r--r--drivers/s390/char/Makefile4
-rw-r--r--drivers/s390/char/sclp.c12
-rw-r--r--drivers/s390/char/sclp.h18
-rw-r--r--drivers/s390/char/sclp_cpi.c2
-rw-r--r--drivers/s390/char/sclp_info.c57
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/sclp_vt220.c2
-rw-r--r--drivers/s390/cio/cio.c10
-rw-r--r--include/asm-s390/processor.h12
-rw-r--r--include/asm-s390/reset.h3
-rw-r--r--include/asm-s390/sclp.h39
21 files changed, 598 insertions, 609 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index dbe3df4b0dab..7c621b8ef683 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -433,7 +433,6 @@ CONFIG_TN3270_CONSOLE=y
433CONFIG_TN3215=y 433CONFIG_TN3215=y
434CONFIG_TN3215_CONSOLE=y 434CONFIG_TN3215_CONSOLE=y
435CONFIG_CCW_CONSOLE=y 435CONFIG_CCW_CONSOLE=y
436CONFIG_SCLP=y
437CONFIG_SCLP_TTY=y 436CONFIG_SCLP_TTY=y
438CONFIG_SCLP_CONSOLE=y 437CONFIG_SCLP_CONSOLE=y
439CONFIG_SCLP_VT220_TTY=y 438CONFIG_SCLP_VT220_TTY=y
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2de811a71a39..5492d25d7d69 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 reset.o \ 7obj-y := bitmap.o traps.o time.o process.o base.o early.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 irq.o ipl.o 9 semaphore.o s390_ext.o debug.o irq.o ipl.o
10 10
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
new file mode 100644
index 000000000000..dc7e5259770f
--- /dev/null
+++ b/arch/s390/kernel/base.S
@@ -0,0 +1,150 @@
1/*
2 * arch/s390/kernel/base.S
3 *
4 * Copyright IBM Corp. 2006,2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 * Michael Holzheu <holzheu@de.ibm.com>
7 */
8
9#include <asm/ptrace.h>
10#include <asm/lowcore.h>
11
12#ifdef CONFIG_64BIT
13
14 .globl s390_base_mcck_handler
15s390_base_mcck_handler:
16 basr %r13,0
170: lg %r15,__LC_PANIC_STACK # load panic stack
18 aghi %r15,-STACK_FRAME_OVERHEAD
19 larl %r1,s390_base_mcck_handler_fn
20 lg %r1,0(%r1)
21 ltgr %r1,%r1
22 jz 1f
23 basr %r14,%r1
241: la %r1,4095
25 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
26 lpswe __LC_MCK_OLD_PSW
27
28 .section .bss
29 .globl s390_base_mcck_handler_fn
30s390_base_mcck_handler_fn:
31 .quad 0
32 .previous
33
34 .globl s390_base_ext_handler
35s390_base_ext_handler:
36 stmg %r0,%r15,__LC_SAVE_AREA
37 basr %r13,0
380: aghi %r15,-STACK_FRAME_OVERHEAD
39 larl %r1,s390_base_ext_handler_fn
40 lg %r1,0(%r1)
41 ltgr %r1,%r1
42 jz 1f
43 basr %r14,%r1
441: lmg %r0,%r15,__LC_SAVE_AREA
45 ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
46 lpswe __LC_EXT_OLD_PSW
47
48 .section .bss
49 .globl s390_base_ext_handler_fn
50s390_base_ext_handler_fn:
51 .quad 0
52 .previous
53
54 .globl s390_base_pgm_handler
55s390_base_pgm_handler:
56 stmg %r0,%r15,__LC_SAVE_AREA
57 basr %r13,0
580: aghi %r15,-STACK_FRAME_OVERHEAD
59 larl %r1,s390_base_pgm_handler_fn
60 lg %r1,0(%r1)
61 ltgr %r1,%r1
62 jz 1f
63 basr %r14,%r1
64 lmg %r0,%r15,__LC_SAVE_AREA
65 lpswe __LC_PGM_OLD_PSW
661: lpswe disabled_wait_psw-0b(%r13)
67
68 .align 8
69disabled_wait_psw:
70 .quad 0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
71
72 .section .bss
73 .globl s390_base_pgm_handler_fn
74s390_base_pgm_handler_fn:
75 .quad 0
76 .previous
77
78#else /* CONFIG_64BIT */
79
80 .globl s390_base_mcck_handler
81s390_base_mcck_handler:
82 basr %r13,0
830: l %r15,__LC_PANIC_STACK # load panic stack
84 ahi %r15,-STACK_FRAME_OVERHEAD
85 l %r1,2f-0b(%r13)
86 l %r1,0(%r1)
87 ltr %r1,%r1
88 jz 1f
89 basr %r14,%r1
901: lm %r0,%r15,__LC_GPREGS_SAVE_AREA
91 lpsw __LC_MCK_OLD_PSW
92
932: .long s390_base_mcck_handler_fn
94
95 .section .bss
96 .globl s390_base_mcck_handler_fn
97s390_base_mcck_handler_fn:
98 .long 0
99 .previous
100
101 .globl s390_base_ext_handler
102s390_base_ext_handler:
103 stm %r0,%r15,__LC_SAVE_AREA
104 basr %r13,0
1050: ahi %r15,-STACK_FRAME_OVERHEAD
106 l %r1,2f-0b(%r13)
107 l %r1,0(%r1)
108 ltr %r1,%r1
109 jz 1f
110 basr %r14,%r1
1111: lm %r0,%r15,__LC_SAVE_AREA
112 ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
113 lpsw __LC_EXT_OLD_PSW
114
1152: .long s390_base_ext_handler_fn
116
117 .section .bss
118 .globl s390_base_ext_handler_fn
119s390_base_ext_handler_fn:
120 .long 0
121 .previous
122
123 .globl s390_base_pgm_handler
124s390_base_pgm_handler:
125 stm %r0,%r15,__LC_SAVE_AREA
126 basr %r13,0
1270: ahi %r15,-STACK_FRAME_OVERHEAD
128 l %r1,2f-0b(%r13)
129 l %r1,0(%r1)
130 ltr %r1,%r1
131 jz 1f
132 basr %r14,%r1
133 lm %r0,%r15,__LC_SAVE_AREA
134 lpsw __LC_PGM_OLD_PSW
135
1361: lpsw disabled_wait_psw-0b(%r13)
137
1382: .long s390_base_pgm_handler_fn
139
140disabled_wait_psw:
141 .align 8
142 .long 0x000a0000,0x00000000 + s390_base_pgm_handler
143
144 .section .bss
145 .globl s390_base_pgm_handler_fn
146s390_base_pgm_handler_fn:
147 .long 0
148 .previous
149
150#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
new file mode 100644
index 000000000000..40dd47970a33
--- /dev/null
+++ b/arch/s390/kernel/early.c
@@ -0,0 +1,307 @@
1/*
2 * arch/s390/kernel/early.c
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Hongjie Yang <hongjie@us.ibm.com>,
6 * Heiko Carstens <heiko.carstens@de.ibm.com>
7 */
8
9#include <linux/init.h>
10#include <linux/errno.h>
11#include <linux/string.h>
12#include <linux/ctype.h>
13#include <linux/lockdep.h>
14#include <linux/module.h>
15#include <linux/pfn.h>
16#include <linux/uaccess.h>
17#include <asm/lowcore.h>
18#include <asm/processor.h>
19#include <asm/sections.h>
20#include <asm/setup.h>
21#include <asm/cpcmd.h>
22#include <asm/sclp.h>
23
24/*
25 * Create a Kernel NSS if the SAVESYS= parameter is defined
26 */
27#define DEFSYS_CMD_SIZE 96
28#define SAVESYS_CMD_SIZE 32
29
30extern int _eshared;
31char kernel_nss_name[NSS_NAME_SIZE + 1];
32
33#ifdef CONFIG_SHARED_KERNEL
34static noinline __init void create_kernel_nss(void)
35{
36 unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
37#ifdef CONFIG_BLK_DEV_INITRD
38 unsigned int sinitrd_pfn, einitrd_pfn;
39#endif
40 int response;
41 char *savesys_ptr;
42 char upper_command_line[COMMAND_LINE_SIZE];
43 char defsys_cmd[DEFSYS_CMD_SIZE];
44 char savesys_cmd[SAVESYS_CMD_SIZE];
45
46 /* Do nothing if we are not running under VM */
47 if (!MACHINE_IS_VM)
48 return;
49
50 /* Convert COMMAND_LINE to upper case */
51 for (i = 0; i < strlen(COMMAND_LINE); i++)
52 upper_command_line[i] = toupper(COMMAND_LINE[i]);
53
54 savesys_ptr = strstr(upper_command_line, "SAVESYS=");
55
56 if (!savesys_ptr)
57 return;
58
59 savesys_ptr += 8; /* Point to the beginning of the NSS name */
60 for (i = 0; i < NSS_NAME_SIZE; i++) {
61 if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
62 break;
63 kernel_nss_name[i] = savesys_ptr[i];
64 }
65
66 stext_pfn = PFN_DOWN(__pa(&_stext));
67 eshared_pfn = PFN_DOWN(__pa(&_eshared));
68 end_pfn = PFN_UP(__pa(&_end));
69 min_size = end_pfn << 2;
70
71 sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
72 kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
73 eshared_pfn, end_pfn);
74
75#ifdef CONFIG_BLK_DEV_INITRD
76 if (INITRD_START && INITRD_SIZE) {
77 sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
78 einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
79 min_size = einitrd_pfn << 2;
80 sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
81 sinitrd_pfn, einitrd_pfn);
82 }
83#endif
84
85 sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
86 sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
87 kernel_nss_name, kernel_nss_name);
88
89 __cpcmd(defsys_cmd, NULL, 0, &response);
90
91 if (response != 0)
92 return;
93
94 __cpcmd(savesys_cmd, NULL, 0, &response);
95
96 if (response != strlen(savesys_cmd))
97 return;
98
99 ipl_flags = IPL_NSS_VALID;
100}
101
102#else /* CONFIG_SHARED_KERNEL */
103
104static inline void create_kernel_nss(void) { }
105
106#endif /* CONFIG_SHARED_KERNEL */
107
108/*
109 * Clear bss memory
110 */
111static noinline __init void clear_bss_section(void)
112{
113 memset(__bss_start, 0, _end - __bss_start);
114}
115
116/*
117 * Initialize storage key for kernel pages
118 */
119static noinline __init void init_kernel_storage_key(void)
120{
121 unsigned long end_pfn, init_pfn;
122
123 end_pfn = PFN_UP(__pa(&_end));
124
125 for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
126 page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
127}
128
129static noinline __init void detect_machine_type(void)
130{
131 struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
132
133 asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
134
135 /* Running under z/VM ? */
136 if (cpuinfo->cpu_id.version == 0xff)
137 machine_flags |= 1;
138
139 /* Running on a P/390 ? */
140 if (cpuinfo->cpu_id.machine == 0x7490)
141 machine_flags |= 4;
142}
143
144static noinline __init int memory_fast_detect(void)
145{
146
147 unsigned long val0 = 0;
148 unsigned long val1 = 0xc;
149 int ret = -ENOSYS;
150
151 if (ipl_flags & IPL_NSS_VALID)
152 return -ENOSYS;
153
154 asm volatile(
155 " diag %1,%2,0x260\n"
156 "0: lhi %0,0\n"
157 "1:\n"
158 EX_TABLE(0b,1b)
159 : "+d" (ret), "+d" (val0), "+d" (val1) : : "cc");
160
161 if (ret || val0 != val1)
162 return -ENOSYS;
163
164 memory_chunk[0].size = val0;
165 return 0;
166}
167
168#define ADDR2G (1UL << 31)
169
170static noinline __init unsigned long sclp_memory_detect(void)
171{
172 struct sclp_readinfo_sccb *sccb;
173 unsigned long long memsize;
174
175 sccb = &s390_readinfo_sccb;
176
177 if (sccb->header.response_code != 0x10)
178 return 0;
179
180 if (sccb->rnsize)
181 memsize = sccb->rnsize << 20;
182 else
183 memsize = sccb->rnsize2 << 20;
184 if (sccb->rnmax)
185 memsize *= sccb->rnmax;
186 else
187 memsize *= sccb->rnmax2;
188#ifndef CONFIG_64BIT
189 /*
190 * Can't deal with more than 2G in 31 bit addressing mode, so
191 * limit the value in order to avoid strange side effects.
192 */
193 if (memsize > ADDR2G)
194 memsize = ADDR2G;
195#endif
196 return (unsigned long) memsize;
197}
198
199static inline __init unsigned long __tprot(unsigned long addr)
200{
201 int cc = -1;
202
203 asm volatile(
204 " tprot 0(%1),0\n"
205 "0: ipm %0\n"
206 " srl %0,28\n"
207 "1:\n"
208 EX_TABLE(0b,1b)
209 : "+d" (cc) : "a" (addr) : "cc");
210 return (unsigned long)cc;
211}
212
213/* Checking memory in 128KB increments. */
214#define CHUNK_INCR (1UL << 17)
215
216static noinline __init void find_memory_chunks(unsigned long memsize)
217{
218 unsigned long addr = 0, old_addr = 0;
219 unsigned long old_cc = CHUNK_READ_WRITE;
220 unsigned long cc;
221 int chunk = 0;
222
223 while (chunk < MEMORY_CHUNKS) {
224 cc = __tprot(addr);
225 while (cc == old_cc) {
226 addr += CHUNK_INCR;
227 cc = __tprot(addr);
228#ifndef CONFIG_64BIT
229 if (addr == ADDR2G)
230 break;
231#endif
232 }
233
234 if (old_addr != addr &&
235 (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) {
236 memory_chunk[chunk].addr = old_addr;
237 memory_chunk[chunk].size = addr - old_addr;
238 memory_chunk[chunk].type = old_cc;
239 chunk++;
240 }
241
242 old_addr = addr;
243 old_cc = cc;
244
245#ifndef CONFIG_64BIT
246 if (addr == ADDR2G)
247 break;
248#endif
249 /*
250 * Finish memory detection at the first hole, unless
251 * - we reached the hsa -> skip it.
252 * - we know there must be more.
253 */
254 if (cc == -1UL && !memsize && old_addr != ADDR2G)
255 break;
256 if (memsize && addr >= memsize)
257 break;
258 }
259}
260
261static __init void early_pgm_check_handler(void)
262{
263 unsigned long addr;
264 const struct exception_table_entry *fixup;
265
266 addr = S390_lowcore.program_old_psw.addr;
267 fixup = search_exception_tables(addr & PSW_ADDR_INSN);
268 if (!fixup)
269 disabled_wait(0);
270 S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
271}
272
273static noinline __init void setup_lowcore_early(void)
274{
275 psw_t psw;
276
277 psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
278 psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
279 S390_lowcore.external_new_psw = psw;
280 psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
281 S390_lowcore.program_new_psw = psw;
282 s390_base_pgm_handler_fn = early_pgm_check_handler;
283}
284
285/*
286 * Save ipl parameters, clear bss memory, initialize storage keys
287 * and create a kernel NSS at startup if the SAVESYS= parm is defined
288 */
289void __init startup_init(void)
290{
291 unsigned long memsize;
292
293 ipl_save_parameters();
294 clear_bss_section();
295 init_kernel_storage_key();
296 lockdep_init();
297 lockdep_off();
298 detect_machine_type();
299 create_kernel_nss();
300 sort_main_extable();
301 setup_lowcore_early();
302 sclp_readinfo_early();
303 memsize = sclp_memory_detect();
304 if (memory_fast_detect() < 0)
305 find_memory_chunks(memsize);
306 lockdep_on();
307}
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index b3dcdcdc80c0..453fd3b4edea 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -58,145 +58,6 @@ startup_continue:
58 l %r14,.Lstartup_init-.LPG1(%r13) 58 l %r14,.Lstartup_init-.LPG1(%r13)
59 basr %r14,%r14 59 basr %r14,%r14
60 60
61 l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
62.Lservicecall:
63 stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
64
65 stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0
66 la %r1,0x200 # set bit 22
67 o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
68 st %r1,.Lcr-.LPG1(%r13)
69 lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0
70
71 mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
72 la %r1, .Lsclph-.LPG1(%r13)
73 a %r1,__LC_EXT_NEW_PSW+4 # set handler
74 st %r1,__LC_EXT_NEW_PSW+4
75
76 l %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff
77 lr %r1,%r4 # our sccb
78 .insn rre,0xb2200000,%r2,%r1 # service call
79 ipm %r1
80 srl %r1,28 # get cc code
81 xr %r3, %r3
82 chi %r1,3
83 be .Lfchunk-.LPG1(%r13) # leave
84 chi %r1,2
85 be .Lservicecall-.LPG1(%r13)
86 lpsw .Lwaitsclp-.LPG1(%r13)
87.Lsclph:
88 lh %r1,.Lsccbr-.Lsccb(%r4)
89 chi %r1,0x10 # 0x0010 is the sucess code
90 je .Lprocsccb # let's process the sccb
91 chi %r1,0x1f0
92 bne .Lfchunk-.LPG1(%r13) # unhandled error code
93 c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced
94 bne .Lfchunk-.LPG1(%r13) # if no, give up
95 l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP
96 b .Lservicecall-.LPG1(%r13)
97.Lprocsccb:
98 lhi %r1,0
99 icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
100 jnz .Lscnd
101 lhi %r1,0x800 # otherwise report 2GB
102.Lscnd:
103 lhi %r3,0x800 # limit reported memory size to 2GB
104 cr %r1,%r3
105 jl .Lno2gb
106 lr %r1,%r3
107.Lno2gb:
108 xr %r3,%r3 # same logic
109 ic %r3,.Lscpa1-.Lsccb(%r4)
110 chi %r3,0x00
111 jne .Lcompmem
112 l %r3,.Lscpa2-.Lsccb(%r4)
113.Lcompmem:
114 mr %r2,%r1 # mem in MB on 128-bit
115 l %r1,.Lonemb-.LPG1(%r13)
116 mr %r2,%r1 # mem size in bytes in %r3
117 b .Lfchunk-.LPG1(%r13)
118
119 .align 4
120.Linittu:
121 .long init_thread_union
122.Lstartup_init:
123 .long startup_init
124.Lpmask:
125 .byte 0
126 .align 8
127.Lpcext:.long 0x00080000,0x80000000
128.Lcr:
129 .long 0x00 # place holder for cr0
130 .align 8
131.Lwaitsclp:
132 .long 0x010a0000,0x80000000 + .Lsclph
133.Lrcp:
134 .int 0x00120001 # Read SCP forced code
135.Lrcp2:
136 .int 0x00020001 # Read SCP code
137.Lonemb:
138 .int 0x100000
139.Lfchunk:
140
141#
142# find memory chunks.
143#
144 lr %r9,%r3 # end of mem
145 mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
146 la %r1,1 # test in increments of 128KB
147 sll %r1,17
148 l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
149 slr %r4,%r4 # set start of chunk to zero
150 slr %r5,%r5 # set end of chunk to zero
151 slr %r6,%r6 # set access code to zero
152 la %r10,MEMORY_CHUNKS # number of chunks
153.Lloop:
154 tprot 0(%r5),0 # test protection of first byte
155 ipm %r7
156 srl %r7,28
157 clr %r6,%r7 # compare cc with last access code
158 be .Lsame-.LPG1(%r13)
159 lhi %r8,0 # no program checks
160 b .Lsavchk-.LPG1(%r13)
161.Lsame:
162 ar %r5,%r1 # add 128KB to end of chunk
163 bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
164.Lchkmem: # > 2GB or tprot got a program check
165 lhi %r8,1 # set program check flag
166.Lsavchk:
167 clr %r4,%r5 # chunk size > 0?
168 be .Lchkloop-.LPG1(%r13)
169 st %r4,0(%r3) # store start address of chunk
170 lr %r0,%r5
171 slr %r0,%r4
172 st %r0,4(%r3) # store size of chunk
173 st %r6,8(%r3) # store type of chunk
174 la %r3,12(%r3)
175 ahi %r10,-1 # update chunk number
176.Lchkloop:
177 lr %r6,%r7 # set access code to last cc
178 # we got an exception or we're starting a new
179 # chunk , we must check if we should
180 # still try to find valid memory (if we detected
181 # the amount of available storage), and if we
182 # have chunks left
183 xr %r0,%r0
184 clr %r0,%r9 # did we detect memory?
185 je .Ldonemem # if not, leave
186 chi %r10,0 # do we have chunks left?
187 je .Ldonemem
188 chi %r8,1 # program check ?
189 je .Lpgmchk
190 lr %r4,%r5 # potential new chunk
191 alr %r5,%r1 # add 128KB to end of chunk
192 j .Llpcnt
193.Lpgmchk:
194 alr %r5,%r1 # add 128KB to end of chunk
195 lr %r4,%r5 # potential new chunk
196.Llpcnt:
197 clr %r5,%r9 # should we go on?
198 jl .Lloop
199.Ldonemem:
200 l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags 61 l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
201# 62#
202# find out if we have an IEEE fpu 63# find out if we have an IEEE fpu
@@ -273,7 +134,6 @@ startup_continue:
273 .long 0 # cr15: linkage stack operations 134 .long 0 # cr15: linkage stack operations
274.Lduct: .long 0,0,0,0,0,0,0,0 135.Lduct: .long 0,0,0,0,0,0,0,0
275 .long 0,0,0,0,0,0,0,0 136 .long 0,0,0,0,0,0,0,0
276.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem
277.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu 137.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
278.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp 138.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
279.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg 139.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
@@ -284,7 +144,9 @@ startup_continue:
284.Lbss_bgn: .long __bss_start 144.Lbss_bgn: .long __bss_start
285.Lbss_end: .long _end 145.Lbss_end: .long _end
286.Lparmaddr: .long PARMAREA 146.Lparmaddr: .long PARMAREA
287.Lsccbaddr: .long .Lsccb 147.Linittu: .long init_thread_union
148.Lstartup_init:
149 .long startup_init
288 150
289 .globl ipl_schib 151 .globl ipl_schib
290ipl_schib: 152ipl_schib:
@@ -300,26 +162,6 @@ ipl_devno:
300 .word 0 162 .word 0
301 163
302 .org 0x12000 164 .org 0x12000
303.globl s390_readinfo_sccb
304s390_readinfo_sccb:
305.Lsccb:
306 .hword 0x1000 # length, one page
307 .byte 0x00,0x00,0x00
308 .byte 0x80 # variable response bit set
309.Lsccbr:
310 .hword 0x00 # response code
311.Lscpincr1:
312 .hword 0x00
313.Lscpa1:
314 .byte 0x00
315 .fill 89,1,0
316.Lscpa2:
317 .int 0x00
318.Lscpincr2:
319 .quad 0x00
320 .fill 3984,1,0
321 .org 0x13000
322
323#ifdef CONFIG_SHARED_KERNEL 165#ifdef CONFIG_SHARED_KERNEL
324 .org 0x100000 166 .org 0x100000
325#endif 167#endif
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 030a1c95f47c..b8fec4e5c5d4 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -65,162 +65,6 @@ startup_continue:
65 brasl %r14,startup_init 65 brasl %r14,startup_init
66 # set program check new psw mask 66 # set program check new psw mask
67 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) 67 mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
68 larl %r1,.Lslowmemdetect # set program check address
69 stg %r1,__LC_PGM_NEW_PSW+8
70 lghi %r1,0xc
71 diag %r0,%r1,0x260 # get memory size of virtual machine
72 cgr %r0,%r1 # different? -> old detection routine
73 jne .Lslowmemdetect
74 larl %r3,ipl_flags
75 llgt %r3,0(%r3)
76 chi %r3,4 # ipled from an kernel NSS
77 je .Lslowmemdetect
78 aghi %r1,1 # size is one more than end
79 larl %r2,memory_chunk
80 stg %r1,8(%r2) # store size of chunk
81
82.Lslowmemdetect:
83 l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
84.Lservicecall:
85 stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
86
87 stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0
88 la %r1,0x200 # set bit 22
89 og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
90 stg %r1,.Lcr-.LPG1(%r13)
91 lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0
92
93 mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
94 larl %r1,.Lsclph
95 stg %r1,__LC_EXT_NEW_PSW+8 # set handler
96
97 larl %r4,.Lsccb # %r4 is our index for sccb stuff
98 lgr %r1,%r4 # our sccb
99 .insn rre,0xb2200000,%r2,%r1 # service call
100 ipm %r1
101 srl %r1,28 # get cc code
102 xr %r3,%r3
103 chi %r1,3
104 be .Lfchunk-.LPG1(%r13) # leave
105 chi %r1,2
106 be .Lservicecall-.LPG1(%r13)
107 lpswe .Lwaitsclp-.LPG1(%r13)
108.Lsclph:
109 lh %r1,.Lsccbr-.Lsccb(%r4)
110 chi %r1,0x10 # 0x0010 is the sucess code
111 je .Lprocsccb # let's process the sccb
112 chi %r1,0x1f0
113 bne .Lfchunk-.LPG1(%r13) # unhandled error code
114 c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced
115 bne .Lfchunk-.LPG1(%r13) # if no, give up
116 l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP
117 b .Lservicecall-.LPG1(%r13)
118.Lprocsccb:
119 lghi %r1,0
120 icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
121 jnz .Lscnd
122 lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
123.Lscnd:
124 xr %r3,%r3 # same logic
125 ic %r3,.Lscpa1-.Lsccb(%r4)
126 chi %r3,0x00
127 jne .Lcompmem
128 l %r3,.Lscpa2-.Lsccb(%r4)
129.Lcompmem:
130 mlgr %r2,%r1 # mem in MB on 128-bit
131 l %r1,.Lonemb-.LPG1(%r13)
132 mlgr %r2,%r1 # mem size in bytes in %r3
133 b .Lfchunk-.LPG1(%r13)
134
135 .align 4
136.Lpmask:
137 .byte 0
138 .align 8
139.Lcr:
140 .quad 0x00 # place holder for cr0
141.Lwaitsclp:
142 .quad 0x0102000180000000,.Lsclph
143.Lrcp:
144 .int 0x00120001 # Read SCP forced code
145.Lrcp2:
146 .int 0x00020001 # Read SCP code
147.Lonemb:
148 .int 0x100000
149
150.Lfchunk:
151
152#
153# find memory chunks.
154#
155 larl %r9,memory_chunk # skip tprot loop if diag260
156 lg %r9,8(%r9) # memory detection was successful
157 ltgr %r9,%r9
158 jne .Ldonemem
159
160 lgr %r9,%r3 # end of mem
161 larl %r1,.Lchkmem # set program check address
162 stg %r1,__LC_PGM_NEW_PSW+8
163 la %r1,1 # test in increments of 128KB
164 sllg %r1,%r1,17
165 larl %r3,memory_chunk
166 slgr %r4,%r4 # set start of chunk to zero
167 slgr %r5,%r5 # set end of chunk to zero
168 slr %r6,%r6 # set access code to zero
169 la %r10,MEMORY_CHUNKS # number of chunks
170.Lloop:
171 tprot 0(%r5),0 # test protection of first byte
172 ipm %r7
173 srl %r7,28
174 clr %r6,%r7 # compare cc with last access code
175 je .Lsame
176 lghi %r8,0 # no program checks
177 j .Lsavchk
178.Lsame:
179 algr %r5,%r1 # add 128KB to end of chunk
180 # no need to check here,
181 brc 12,.Lloop # this is the same chunk
182.Lchkmem: # > 16EB or tprot got a program check
183 lghi %r8,1 # set program check flag
184.Lsavchk:
185 clgr %r4,%r5 # chunk size > 0?
186 je .Lchkloop
187 stg %r4,0(%r3) # store start address of chunk
188 lgr %r0,%r5
189 slgr %r0,%r4
190 stg %r0,8(%r3) # store size of chunk
191 st %r6,20(%r3) # store type of chunk
192 la %r3,24(%r3)
193 ahi %r10,-1 # update chunk number
194.Lchkloop:
195 lr %r6,%r7 # set access code to last cc
196 # we got an exception or we're starting a new
197 # chunk , we must check if we should
198 # still try to find valid memory (if we detected
199 # the amount of available storage), and if we
200 # have chunks left
201 lghi %r4,1
202 sllg %r4,%r4,31
203 clgr %r5,%r4
204 je .Lhsaskip
205 xr %r0, %r0
206 clgr %r0, %r9 # did we detect memory?
207 je .Ldonemem # if not, leave
208 chi %r10, 0 # do we have chunks left?
209 je .Ldonemem
210.Lhsaskip:
211 chi %r8,1 # program check ?
212 je .Lpgmchk
213 lgr %r4,%r5 # potential new chunk
214 algr %r5,%r1 # add 128KB to end of chunk
215 j .Llpcnt
216.Lpgmchk:
217 algr %r5,%r1 # add 128KB to end of chunk
218 lgr %r4,%r5 # potential new chunk
219.Llpcnt:
220 clgr %r5,%r9 # should we go on?
221 jl .Lloop
222.Ldonemem:
223
224 larl %r12,machine_flags 68 larl %r12,machine_flags
225# 69#
226# find out if we have the MVPG instruction 70# find out if we have the MVPG instruction
@@ -324,25 +168,6 @@ ipl_devno:
324 .word 0 168 .word 0
325 169
326 .org 0x12000 170 .org 0x12000
327.globl s390_readinfo_sccb
328s390_readinfo_sccb:
329.Lsccb:
330 .hword 0x1000 # length, one page
331 .byte 0x00,0x00,0x00
332 .byte 0x80 # variable response bit set
333.Lsccbr:
334 .hword 0x00 # response code
335.Lscpincr1:
336 .hword 0x00
337.Lscpa1:
338 .byte 0x00
339 .fill 89,1,0
340.Lscpa2:
341 .int 0x00
342.Lscpincr2:
343 .quad 0x00
344 .fill 3984,1,0
345 .org 0x13000
346 171
347#ifdef CONFIG_SHARED_KERNEL 172#ifdef CONFIG_SHARED_KERNEL
348 .org 0x100000 173 .org 0x100000
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 13eacce62011..052259530651 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -20,14 +20,13 @@
20#include <asm/cio.h> 20#include <asm/cio.h>
21#include <asm/ebcdic.h> 21#include <asm/ebcdic.h>
22#include <asm/reset.h> 22#include <asm/reset.h>
23#include <asm/sclp.h>
23 24
24#define IPL_PARM_BLOCK_VERSION 0 25#define IPL_PARM_BLOCK_VERSION 0
25#define LOADPARM_LEN 8
26 26
27extern char s390_readinfo_sccb[]; 27#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
28#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010) 28#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
29#define SCCB_LOADPARM (&s390_readinfo_sccb[24]) 29#define SCCB_FLAG (s390_readinfo_sccb.flags)
30#define SCCB_FLAG (s390_readinfo_sccb[91])
31 30
32enum ipl_type { 31enum ipl_type {
33 IPL_TYPE_NONE = 1, 32 IPL_TYPE_NONE = 1,
@@ -1080,8 +1079,6 @@ static void do_reset_calls(void)
1080 reset->fn(); 1079 reset->fn();
1081} 1080}
1082 1081
1083extern void reset_mcck_handler(void);
1084extern void reset_pgm_handler(void);
1085extern __u32 dump_prefix_page; 1082extern __u32 dump_prefix_page;
1086 1083
1087void s390_reset_system(void) 1084void s390_reset_system(void)
@@ -1105,12 +1102,12 @@ void s390_reset_system(void)
1105 /* Set new machine check handler */ 1102 /* Set new machine check handler */
1106 S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; 1103 S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1107 S390_lowcore.mcck_new_psw.addr = 1104 S390_lowcore.mcck_new_psw.addr =
1108 PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; 1105 PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
1109 1106
1110 /* Set new program check handler */ 1107 /* Set new program check handler */
1111 S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; 1108 S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
1112 S390_lowcore.program_new_psw.addr = 1109 S390_lowcore.program_new_psw.addr =
1113 PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler; 1110 PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
1114 1111
1115 do_reset_calls(); 1112 do_reset_calls();
1116} 1113}
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
deleted file mode 100644
index 8a87355161fa..000000000000
--- a/arch/s390/kernel/reset.S
+++ /dev/null
@@ -1,90 +0,0 @@
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 * Michael Holzheu <holzheu@de.ibm.com>
7 */
8
9#include <asm/ptrace.h>
10#include <asm/lowcore.h>
11
12#ifdef CONFIG_64BIT
13
14 .globl reset_mcck_handler
15reset_mcck_handler:
16 basr %r13,0
170: lg %r15,__LC_PANIC_STACK # load panic stack
18 aghi %r15,-STACK_FRAME_OVERHEAD
19 lg %r1,s390_reset_mcck_handler-0b(%r13)
20 ltgr %r1,%r1
21 jz 1f
22 basr %r14,%r1
231: la %r1,4095
24 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
25 lpswe __LC_MCK_OLD_PSW
26
27 .globl s390_reset_mcck_handler
28s390_reset_mcck_handler:
29 .quad 0
30
31 .globl reset_pgm_handler
32reset_pgm_handler:
33 stmg %r0,%r15,__LC_SAVE_AREA
34 basr %r13,0
350: lg %r15,__LC_PANIC_STACK # load panic stack
36 aghi %r15,-STACK_FRAME_OVERHEAD
37 lg %r1,s390_reset_pgm_handler-0b(%r13)
38 ltgr %r1,%r1
39 jz 1f
40 basr %r14,%r1
41 lmg %r0,%r15,__LC_SAVE_AREA
42 lpswe __LC_PGM_OLD_PSW
431: lpswe disabled_wait_psw-0b(%r13)
44 .globl s390_reset_pgm_handler
45s390_reset_pgm_handler:
46 .quad 0
47 .align 8
48disabled_wait_psw:
49 .quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler
50
51#else /* CONFIG_64BIT */
52
53 .globl reset_mcck_handler
54reset_mcck_handler:
55 basr %r13,0
560: l %r15,__LC_PANIC_STACK # load panic stack
57 ahi %r15,-STACK_FRAME_OVERHEAD
58 l %r1,s390_reset_mcck_handler-0b(%r13)
59 ltr %r1,%r1
60 jz 1f
61 basr %r14,%r1
621: lm %r0,%r15,__LC_GPREGS_SAVE_AREA
63 lpsw __LC_MCK_OLD_PSW
64
65 .globl s390_reset_mcck_handler
66s390_reset_mcck_handler:
67 .long 0
68
69 .globl reset_pgm_handler
70reset_pgm_handler:
71 stm %r0,%r15,__LC_SAVE_AREA
72 basr %r13,0
730: l %r15,__LC_PANIC_STACK # load panic stack
74 ahi %r15,-STACK_FRAME_OVERHEAD
75 l %r1,s390_reset_pgm_handler-0b(%r13)
76 ltr %r1,%r1
77 jz 1f
78 basr %r14,%r1
79 lm %r0,%r15,__LC_SAVE_AREA
80 lpsw __LC_PGM_OLD_PSW
81
821: lpsw disabled_wait_psw-0b(%r13)
83 .globl s390_reset_pgm_handler
84s390_reset_pgm_handler:
85 .long 0
86disabled_wait_psw:
87 .align 8
88 .long 0x000a0000,0x00000000 + reset_pgm_handler
89
90#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2fa866f6f711..f73a11528217 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -284,140 +284,6 @@ static void __init conmode_default(void)
284 } 284 }
285} 285}
286 286
287/*
288 * Create a Kernel NSS if the SAVESYS= parameter is defined
289*/
290#define DEFSYS_CMD_SIZE 96
291#define SAVESYS_CMD_SIZE 32
292
293extern int _eshared;
294char kernel_nss_name[NSS_NAME_SIZE + 1];
295
296#ifdef CONFIG_SHARED_KERNEL
297static __init void create_kernel_nss(void)
298{
299 unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
300#ifdef CONFIG_BLK_DEV_INITRD
301 unsigned int sinitrd_pfn, einitrd_pfn;
302#endif
303 int response;
304 char *savesys_ptr;
305 char upper_command_line[COMMAND_LINE_SIZE];
306 char defsys_cmd[DEFSYS_CMD_SIZE];
307 char savesys_cmd[SAVESYS_CMD_SIZE];
308
309 /* Do nothing if we are not running under VM */
310 if (!MACHINE_IS_VM)
311 return;
312
313 /* Convert COMMAND_LINE to upper case */
314 for (i = 0; i < strlen(COMMAND_LINE); i++)
315 upper_command_line[i] = toupper(COMMAND_LINE[i]);
316
317 savesys_ptr = strstr(upper_command_line, "SAVESYS=");
318
319 if (!savesys_ptr)
320 return;
321
322 savesys_ptr += 8; /* Point to the beginning of the NSS name */
323 for (i = 0; i < NSS_NAME_SIZE; i++) {
324 if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
325 break;
326 kernel_nss_name[i] = savesys_ptr[i];
327 }
328
329 stext_pfn = PFN_DOWN(__pa(&_stext));
330 eshared_pfn = PFN_DOWN(__pa(&_eshared));
331 end_pfn = PFN_UP(__pa(&_end));
332 min_size = end_pfn << 2;
333
334 sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
335 kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
336 eshared_pfn, end_pfn);
337
338#ifdef CONFIG_BLK_DEV_INITRD
339 if (INITRD_START && INITRD_SIZE) {
340 sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
341 einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
342 min_size = einitrd_pfn << 2;
343 sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
344 sinitrd_pfn, einitrd_pfn);
345 }
346#endif
347
348 sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
349 sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
350 kernel_nss_name, kernel_nss_name);
351
352 __cpcmd(defsys_cmd, NULL, 0, &response);
353
354 if (response != 0)
355 return;
356
357 __cpcmd(savesys_cmd, NULL, 0, &response);
358
359 if (response != strlen(savesys_cmd))
360 return;
361
362 ipl_flags = IPL_NSS_VALID;
363}
364
365#else /* CONFIG_SHARED_KERNEL */
366
367static inline void create_kernel_nss(void) { }
368
369#endif /* CONFIG_SHARED_KERNEL */
370
371/*
372 * Clear bss memory
373 */
374static __init void clear_bss_section(void)
375{
376 memset(__bss_start, 0, _end - __bss_start);
377}
378
379/*
380 * Initialize storage key for kernel pages
381 */
382static __init void init_kernel_storage_key(void)
383{
384 unsigned long end_pfn, init_pfn;
385
386 end_pfn = PFN_UP(__pa(&_end));
387
388 for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
389 page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
390}
391
392static __init void detect_machine_type(void)
393{
394 struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
395
396 asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
397
398 /* Running under z/VM ? */
399 if (cpuinfo->cpu_id.version == 0xff)
400 machine_flags |= 1;
401
402 /* Running on a P/390 ? */
403 if (cpuinfo->cpu_id.machine == 0x7490)
404 machine_flags |= 4;
405}
406
407/*
408 * Save ipl parameters, clear bss memory, initialize storage keys
409 * and create a kernel NSS at startup if the SAVESYS= parm is defined
410 */
411void __init startup_init(void)
412{
413 ipl_save_parameters();
414 clear_bss_section();
415 init_kernel_storage_key();
416 lockdep_init();
417 detect_machine_type();
418 create_kernel_nss();
419}
420
421#ifdef CONFIG_SMP 287#ifdef CONFIG_SMP
422void (*_machine_restart)(char *command) = machine_restart_smp; 288void (*_machine_restart)(char *command) = machine_restart_smp;
423void (*_machine_halt)(void) = machine_halt_smp; 289void (*_machine_halt)(void) = machine_halt_smp;
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index ae89b9b88743..165af398fdea 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -103,14 +103,8 @@ config CCW_CONSOLE
103 depends on TN3215_CONSOLE || TN3270_CONSOLE 103 depends on TN3215_CONSOLE || TN3270_CONSOLE
104 default y 104 default y
105 105
106config SCLP
107 bool "Support for SCLP"
108 help
109 Include support for the SCLP interface to the service element.
110
111config SCLP_TTY 106config SCLP_TTY
112 bool "Support for SCLP line mode terminal" 107 bool "Support for SCLP line mode terminal"
113 depends on SCLP
114 help 108 help
115 Include support for IBM SCLP line-mode terminals. 109 Include support for IBM SCLP line-mode terminals.
116 110
@@ -123,7 +117,6 @@ config SCLP_CONSOLE
123 117
124config SCLP_VT220_TTY 118config SCLP_VT220_TTY
125 bool "Support for SCLP VT220-compatible terminal" 119 bool "Support for SCLP VT220-compatible terminal"
126 depends on SCLP
127 help 120 help
128 Include support for an IBM SCLP VT220-compatible terminal. 121 Include support for an IBM SCLP VT220-compatible terminal.
129 122
@@ -136,7 +129,6 @@ config SCLP_VT220_CONSOLE
136 129
137config SCLP_CPI 130config SCLP_CPI
138 tristate "Control-Program Identification" 131 tristate "Control-Program Identification"
139 depends on SCLP
140 help 132 help
141 This option enables the hardware console interface for system 133 This option enables the hardware console interface for system
142 identification. This is commonly used for workload management and 134 identification. This is commonly used for workload management and
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index c3e97b4fc186..293e667b50f2 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -2,7 +2,8 @@
2# S/390 character devices 2# S/390 character devices
3# 3#
4 4
5obj-y += ctrlchar.o keyboard.o defkeymap.o 5obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
6 sclp_info.o
6 7
7obj-$(CONFIG_TN3270) += raw3270.o 8obj-$(CONFIG_TN3270) += raw3270.o
8obj-$(CONFIG_TN3270_CONSOLE) += con3270.o 9obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
@@ -11,7 +12,6 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o
11 12
12obj-$(CONFIG_TN3215) += con3215.o 13obj-$(CONFIG_TN3215) += con3215.o
13 14
14obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o
15obj-$(CONFIG_SCLP_TTY) += sclp_tty.o 15obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
16obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o 16obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
17obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o 17obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index c1dd19bb7bf8..6a83e2d722a8 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -96,8 +96,8 @@ static int sclp_init_mask(int calculate);
96static int sclp_init(void); 96static int sclp_init(void);
97 97
98/* Perform service call. Return 0 on success, non-zero otherwise. */ 98/* Perform service call. Return 0 on success, non-zero otherwise. */
99static int 99int
100service_call(sclp_cmdw_t command, void *sccb) 100sclp_service_call(sclp_cmdw_t command, void *sccb)
101{ 101{
102 int cc; 102 int cc;
103 103
@@ -173,7 +173,7 @@ __sclp_start_request(struct sclp_req *req)
173 if (sclp_running_state != sclp_running_state_idle) 173 if (sclp_running_state != sclp_running_state_idle)
174 return 0; 174 return 0;
175 del_timer(&sclp_request_timer); 175 del_timer(&sclp_request_timer);
176 rc = service_call(req->command, req->sccb); 176 rc = sclp_service_call(req->command, req->sccb);
177 req->start_count++; 177 req->start_count++;
178 178
179 if (rc == 0) { 179 if (rc == 0) {
@@ -325,7 +325,7 @@ __sclp_make_read_req(void)
325 sccb = (struct sccb_header *) sclp_read_sccb; 325 sccb = (struct sccb_header *) sclp_read_sccb;
326 clear_page(sccb); 326 clear_page(sccb);
327 memset(&sclp_read_req, 0, sizeof(struct sclp_req)); 327 memset(&sclp_read_req, 0, sizeof(struct sclp_req));
328 sclp_read_req.command = SCLP_CMDW_READDATA; 328 sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA;
329 sclp_read_req.status = SCLP_REQ_QUEUED; 329 sclp_read_req.status = SCLP_REQ_QUEUED;
330 sclp_read_req.start_count = 0; 330 sclp_read_req.start_count = 0;
331 sclp_read_req.callback = sclp_read_cb; 331 sclp_read_req.callback = sclp_read_cb;
@@ -628,7 +628,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask)
628 sccb = (struct init_sccb *) sclp_init_sccb; 628 sccb = (struct init_sccb *) sclp_init_sccb;
629 clear_page(sccb); 629 clear_page(sccb);
630 memset(&sclp_init_req, 0, sizeof(struct sclp_req)); 630 memset(&sclp_init_req, 0, sizeof(struct sclp_req));
631 sclp_init_req.command = SCLP_CMDW_WRITEMASK; 631 sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK;
632 sclp_init_req.status = SCLP_REQ_FILLED; 632 sclp_init_req.status = SCLP_REQ_FILLED;
633 sclp_init_req.start_count = 0; 633 sclp_init_req.start_count = 0;
634 sclp_init_req.callback = NULL; 634 sclp_init_req.callback = NULL;
@@ -831,7 +831,7 @@ sclp_check_interface(void)
831 for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { 831 for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) {
832 __sclp_make_init_req(0, 0); 832 __sclp_make_init_req(0, 0);
833 sccb = (struct init_sccb *) sclp_init_req.sccb; 833 sccb = (struct init_sccb *) sclp_init_req.sccb;
834 rc = service_call(sclp_init_req.command, sccb); 834 rc = sclp_service_call(sclp_init_req.command, sccb);
835 if (rc == -EIO) 835 if (rc == -EIO)
836 break; 836 break;
837 sclp_init_req.status = SCLP_REQ_RUNNING; 837 sclp_init_req.status = SCLP_REQ_RUNNING;
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 2c71d6ee7b5b..7d29ab45a6ed 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -12,7 +12,7 @@
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/list.h> 14#include <linux/list.h>
15 15#include <asm/sclp.h>
16#include <asm/ebcdic.h> 16#include <asm/ebcdic.h>
17 17
18/* maximum number of pages concerning our own memory management */ 18/* maximum number of pages concerning our own memory management */
@@ -49,9 +49,11 @@
49 49
50typedef unsigned int sclp_cmdw_t; 50typedef unsigned int sclp_cmdw_t;
51 51
52#define SCLP_CMDW_READDATA 0x00770005 52#define SCLP_CMDW_READ_EVENT_DATA 0x00770005
53#define SCLP_CMDW_WRITEDATA 0x00760005 53#define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
54#define SCLP_CMDW_WRITEMASK 0x00780005 54#define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005
55#define SCLP_CMDW_READ_SCP_INFO 0x00020001
56#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
55 57
56#define GDS_ID_MDSMU 0x1310 58#define GDS_ID_MDSMU 0x1310
57#define GDS_ID_MDSRouteInfo 0x1311 59#define GDS_ID_MDSRouteInfo 0x1311
@@ -66,13 +68,6 @@ typedef unsigned int sclp_cmdw_t;
66 68
67typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ 69typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
68 70
69struct sccb_header {
70 u16 length;
71 u8 function_code;
72 u8 control_mask[3];
73 u16 response_code;
74} __attribute__((packed));
75
76struct gds_subvector { 71struct gds_subvector {
77 u8 length; 72 u8 length;
78 u8 key; 73 u8 key;
@@ -131,6 +126,7 @@ void sclp_unregister(struct sclp_register *reg);
131int sclp_remove_processed(struct sccb_header *sccb); 126int sclp_remove_processed(struct sccb_header *sccb);
132int sclp_deactivate(void); 127int sclp_deactivate(void);
133int sclp_reactivate(void); 128int sclp_reactivate(void);
129int sclp_service_call(sclp_cmdw_t command, void *sccb);
134 130
135/* useful inlines */ 131/* useful inlines */
136 132
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 4f873ae148b7..65aa2c85737f 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -169,7 +169,7 @@ cpi_prepare_req(void)
169 } 169 }
170 170
171 /* prepare request data structure presented to SCLP driver */ 171 /* prepare request data structure presented to SCLP driver */
172 req->command = SCLP_CMDW_WRITEDATA; 172 req->command = SCLP_CMDW_WRITE_EVENT_DATA;
173 req->sccb = sccb; 173 req->sccb = sccb;
174 req->status = SCLP_REQ_FILLED; 174 req->status = SCLP_REQ_FILLED;
175 req->callback = cpi_callback; 175 req->callback = cpi_callback;
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
new file mode 100644
index 000000000000..7bcbe643b087
--- /dev/null
+++ b/drivers/s390/char/sclp_info.c
@@ -0,0 +1,57 @@
1/*
2 * drivers/s390/char/sclp_info.c
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
7
8#include <linux/init.h>
9#include <linux/errno.h>
10#include <linux/string.h>
11#include <asm/sclp.h>
12#include "sclp.h"
13
14struct sclp_readinfo_sccb s390_readinfo_sccb;
15
16void __init sclp_readinfo_early(void)
17{
18 sclp_cmdw_t command;
19 struct sccb_header *sccb;
20 int ret;
21
22 __ctl_set_bit(0, 9); /* enable service signal subclass mask */
23
24 sccb = &s390_readinfo_sccb.header;
25 command = SCLP_CMDW_READ_SCP_INFO_FORCED;
26 while (1) {
27 u16 response;
28
29 memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
30 sccb->length = sizeof(s390_readinfo_sccb);
31 sccb->control_mask[2] = 0x80;
32
33 ret = sclp_service_call(command, &s390_readinfo_sccb);
34
35 if (ret == -EIO)
36 goto out;
37 if (ret == -EBUSY)
38 continue;
39
40 __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
41 PSW_MASK_WAIT | PSW_DEFAULT_KEY);
42 local_irq_disable();
43 barrier();
44
45 response = sccb->response_code;
46
47 if (response == 0x10)
48 break;
49
50 if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
51 break;
52
53 command = SCLP_CMDW_READ_SCP_INFO;
54 }
55out:
56 __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
57}
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index 0c92d3909cca..2486783ea58e 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer,
460 sccb->msg_buf.header.type = EvTyp_PMsgCmd; 460 sccb->msg_buf.header.type = EvTyp_PMsgCmd;
461 else 461 else
462 return -ENOSYS; 462 return -ENOSYS;
463 buffer->request.command = SCLP_CMDW_WRITEDATA; 463 buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
464 buffer->request.status = SCLP_REQ_FILLED; 464 buffer->request.status = SCLP_REQ_FILLED;
465 buffer->request.callback = sclp_writedata_callback; 465 buffer->request.callback = sclp_writedata_callback;
466 buffer->request.callback_data = buffer; 466 buffer->request.callback_data = buffer;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index d8135cd4d7ab..544f137d70d7 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request)
207 request->sclp_req.status = SCLP_REQ_FAILED; 207 request->sclp_req.status = SCLP_REQ_FAILED;
208 return -EIO; 208 return -EIO;
209 } 209 }
210 request->sclp_req.command = SCLP_CMDW_WRITEDATA; 210 request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
211 request->sclp_req.status = SCLP_REQ_FILLED; 211 request->sclp_req.status = SCLP_REQ_FILLED;
212 request->sclp_req.callback = sclp_vt220_callback; 212 request->sclp_req.callback = sclp_vt220_callback;
213 request->sclp_req.callback_data = (void *) request; 213 request->sclp_req.callback_data = (void *) request;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index ad2b37929848..23e71a76cdab 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -895,11 +895,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
895 int rc; 895 int rc;
896 896
897 pgm_check_occured = 0; 897 pgm_check_occured = 0;
898 s390_reset_pgm_handler = cio_reset_pgm_check_handler; 898 s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
899 rc = stsch(schid, addr); 899 rc = stsch(schid, addr);
900 s390_reset_pgm_handler = NULL; 900 s390_base_pgm_handler_fn = NULL;
901 901
902 /* The program check handler could have changed pgm_check_occured */ 902 /* The program check handler could have changed pgm_check_occured. */
903 barrier(); 903 barrier();
904 904
905 if (pgm_check_occured) 905 if (pgm_check_occured)
@@ -957,7 +957,7 @@ static void css_reset(void)
957 /* Reset subchannels. */ 957 /* Reset subchannels. */
958 for_each_subchannel(__shutdown_subchannel_easy, NULL); 958 for_each_subchannel(__shutdown_subchannel_easy, NULL);
959 /* Reset channel paths. */ 959 /* Reset channel paths. */
960 s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; 960 s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler;
961 /* Enable channel report machine checks. */ 961 /* Enable channel report machine checks. */
962 __ctl_set_bit(14, 28); 962 __ctl_set_bit(14, 28);
963 /* Temporarily reenable machine checks. */ 963 /* Temporarily reenable machine checks. */
@@ -982,7 +982,7 @@ static void css_reset(void)
982 local_mcck_disable(); 982 local_mcck_disable();
983 /* Disable channel report machine checks. */ 983 /* Disable channel report machine checks. */
984 __ctl_clear_bit(14, 28); 984 __ctl_clear_bit(14, 28);
985 s390_reset_mcck_handler = NULL; 985 s390_base_mcck_handler_fn = NULL;
986} 986}
987 987
988static struct reset_call css_reset_call = { 988static struct reset_call css_reset_call = {
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index cf71c5449240..4c1b73940351 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -331,6 +331,18 @@ static inline void disabled_wait(unsigned long code)
331} 331}
332 332
333/* 333/*
334 * Basic Machine Check/Program Check Handler.
335 */
336
337extern void s390_base_mcck_handler(void);
338extern void s390_base_pgm_handler(void);
339extern void s390_base_ext_handler(void);
340
341extern void (*s390_base_mcck_handler_fn)(void);
342extern void (*s390_base_pgm_handler_fn)(void);
343extern void (*s390_base_ext_handler_fn)(void);
344
345/*
334 * CPU idle notifier chain. 346 * CPU idle notifier chain.
335 */ 347 */
336#define CPU_IDLE 0 348#define CPU_IDLE 0
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h
index 532e65a2aafc..f584f4a52581 100644
--- a/include/asm-s390/reset.h
+++ b/include/asm-s390/reset.h
@@ -18,7 +18,4 @@ struct reset_call {
18extern void register_reset_call(struct reset_call *reset); 18extern void register_reset_call(struct reset_call *reset);
19extern void unregister_reset_call(struct reset_call *reset); 19extern void unregister_reset_call(struct reset_call *reset);
20extern void s390_reset_system(void); 20extern void s390_reset_system(void);
21extern void (*s390_reset_mcck_handler)(void);
22extern void (*s390_reset_pgm_handler)(void);
23
24#endif /* _ASM_S390_RESET_H */ 21#endif /* _ASM_S390_RESET_H */
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
new file mode 100644
index 000000000000..468b97018405
--- /dev/null
+++ b/include/asm-s390/sclp.h
@@ -0,0 +1,39 @@
1/*
2 * include/asm-s390/sclp.h
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6 */
7
8#ifndef _ASM_S390_SCLP_H
9#define _ASM_S390_SCLP_H
10
11#include <linux/types.h>
12
13struct sccb_header {
14 u16 length;
15 u8 function_code;
16 u8 control_mask[3];
17 u16 response_code;
18} __attribute__((packed));
19
20#define LOADPARM_LEN 8
21
22struct sclp_readinfo_sccb {
23 struct sccb_header header; /* 0-7 */
24 u16 rnmax; /* 8-9 */
25 u8 rnsize; /* 10 */
26 u8 _reserved0[24 - 11]; /* 11-23 */
27 u8 loadparm[LOADPARM_LEN]; /* 24-31 */
28 u8 _reserved1[91 - 32]; /* 32-90 */
29 u8 flags; /* 91 */
30 u8 _reserved2[100 - 92]; /* 92-99 */
31 u32 rnsize2; /* 100-103 */
32 u64 rnmax2; /* 104-111 */
33 u8 _reserved3[4096 - 112]; /* 112-4095 */
34} __attribute__((packed, aligned(4096)));
35
36extern struct sclp_readinfo_sccb s390_readinfo_sccb;
37extern void sclp_readinfo_early(void);
38
39#endif /* _ASM_S390_SCLP_H */