aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/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
8 files changed, 467 insertions, 570 deletions
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;