Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
0ad775db | 2 | * arch/s390/kernel/head64.S |
1da177e4 | 3 | * |
b1b70306 | 4 | * Copyright (C) IBM Corp. 1999,2006 |
0ad775db HC |
5 | * |
6 | * Author(s): Hartmut Penner <hp@de.ibm.com> | |
7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | |
8 | * Rob van der Heij <rvdhei@iae.nl> | |
9 | * Heiko Carstens <heiko.carstens@de.ibm.com> | |
1da177e4 | 10 | * |
1da177e4 LT |
11 | */ |
12 | ||
1da177e4 | 13 | # |
0ad775db | 14 | # startup-code at 0x10000, running in absolute addressing mode |
1da177e4 LT |
15 | # this is called either by the ipl loader or directly by PSW restart |
16 | # or linload or SALIPL | |
17 | # | |
25d83cbf HC |
18 | .org 0x10000 |
19 | startup:basr %r13,0 # get base | |
20 | .LPG0: l %r13,0f-.LPG0(%r13) | |
21 | b 0(%r13) | |
22 | 0: .long startup_continue | |
b1b70306 HC |
23 | |
24 | # | |
25 | # params at 10400 (setup.h) | |
26 | # | |
25d83cbf HC |
27 | .org PARMAREA |
28 | .quad 0 # IPL_DEVICE | |
29 | .quad 0 # INITRD_START | |
30 | .quad 0 # INITRD_SIZE | |
b1b70306 | 31 | |
25d83cbf HC |
32 | .org COMMAND_LINE |
33 | .byte "root=/dev/ram0 ro" | |
34 | .byte 0 | |
b1b70306 | 35 | |
25d83cbf | 36 | .org 0x11000 |
b1b70306 HC |
37 | |
38 | startup_continue: | |
25d83cbf HC |
39 | basr %r13,0 # get base |
40 | .LPG1: sll %r13,1 # remove high order bit | |
41 | srl %r13,1 | |
42 | lhi %r1,1 # mode 1 = esame | |
43 | mvi __LC_AR_MODE_ID,1 # set esame flag | |
44 | slr %r0,%r0 # set cpuid to zero | |
45 | sigp %r1,%r0,0x12 # switch to esame mode | |
46 | sam64 # switch to 64 bit mode | |
47 | lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers | |
48 | lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area | |
49 | # move IPL device to lowcore | |
50 | mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) | |
e87bfe51 HC |
51 | # |
52 | # Setup stack | |
53 | # | |
25d83cbf HC |
54 | larl %r15,init_thread_union |
55 | lg %r14,__TI_task(%r15) # cache current in lowcore | |
56 | stg %r14,__LC_CURRENT | |
57 | aghi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE | |
58 | stg %r15,__LC_KERNEL_STACK # set end of kernel stack | |
59 | aghi %r15,-160 | |
60 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain | |
1da177e4 | 61 | |
25d83cbf | 62 | brasl %r14,ipl_save_parameters |
1da177e4 LT |
63 | # |
64 | # clear bss memory | |
65 | # | |
25d83cbf HC |
66 | larl %r2,__bss_start # start of bss segment |
67 | larl %r3,_end # end of bss segment | |
68 | sgr %r3,%r2 # length of bss | |
69 | sgr %r4,%r4 # | |
70 | sgr %r5,%r5 # set src,length and pad to zero | |
71 | mvcle %r2,%r4,0 # clear mem | |
72 | jo .-4 # branch back, if not finish | |
d57de5a3 HC |
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 | |
d57de5a3 | 84 | j .Ldonemem |
1da177e4 | 85 | |
d57de5a3 | 86 | .Lslowmemdetect: |
25d83cbf | 87 | l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word |
1da177e4 | 88 | .Lservicecall: |
25d83cbf | 89 | stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts |
1da177e4 | 90 | |
25d83cbf HC |
91 | stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0 |
92 | la %r1,0x200 # set bit 22 | |
93 | og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 | |
94 | stg %r1,.Lcr-.LPG1(%r13) | |
95 | lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0 | |
1da177e4 | 96 | |
25d83cbf HC |
97 | mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw |
98 | larl %r1,.Lsclph | |
99 | stg %r1,__LC_EXT_NEW_PSW+8 # set handler | |
1da177e4 | 100 | |
25d83cbf HC |
101 | larl %r4,.Lsccb # %r4 is our index for sccb stuff |
102 | lgr %r1,%r4 # our sccb | |
103 | .insn rre,0xb2200000,%r2,%r1 # service call | |
104 | ipm %r1 | |
105 | srl %r1,28 # get cc code | |
106 | xr %r3,%r3 | |
107 | chi %r1,3 | |
108 | be .Lfchunk-.LPG1(%r13) # leave | |
109 | chi %r1,2 | |
110 | be .Lservicecall-.LPG1(%r13) | |
111 | lpswe .Lwaitsclp-.LPG1(%r13) | |
1da177e4 | 112 | .Lsclph: |
25d83cbf HC |
113 | lh %r1,.Lsccbr-.Lsccb(%r4) |
114 | chi %r1,0x10 # 0x0010 is the sucess code | |
115 | je .Lprocsccb # let's process the sccb | |
116 | chi %r1,0x1f0 | |
117 | bne .Lfchunk-.LPG1(%r13) # unhandled error code | |
118 | c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced | |
119 | bne .Lfchunk-.LPG1(%r13) # if no, give up | |
120 | l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP | |
121 | b .Lservicecall-.LPG1(%r13) | |
1da177e4 | 122 | .Lprocsccb: |
25d83cbf HC |
123 | lghi %r1,0 |
124 | icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 | |
125 | jnz .Lscnd | |
126 | lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one | |
1da177e4 | 127 | .Lscnd: |
25d83cbf HC |
128 | xr %r3,%r3 # same logic |
129 | ic %r3,.Lscpa1-.Lsccb(%r4) | |
130 | chi %r3,0x00 | |
131 | jne .Lcompmem | |
132 | l %r3,.Lscpa2-.Lsccb(%r4) | |
1da177e4 | 133 | .Lcompmem: |
25d83cbf HC |
134 | mlgr %r2,%r1 # mem in MB on 128-bit |
135 | l %r1,.Lonemb-.LPG1(%r13) | |
136 | mlgr %r2,%r1 # mem size in bytes in %r3 | |
137 | b .Lfchunk-.LPG1(%r13) | |
1da177e4 | 138 | |
25d83cbf | 139 | .align 4 |
1da177e4 | 140 | .Lpmask: |
25d83cbf HC |
141 | .byte 0 |
142 | .align 8 | |
1da177e4 | 143 | .Lcr: |
25d83cbf | 144 | .quad 0x00 # place holder for cr0 |
1da177e4 | 145 | .Lwaitsclp: |
25d83cbf | 146 | .quad 0x0102000180000000,.Lsclph |
1da177e4 | 147 | .Lrcp: |
25d83cbf | 148 | .int 0x00120001 # Read SCP forced code |
1da177e4 | 149 | .Lrcp2: |
25d83cbf | 150 | .int 0x00020001 # Read SCP code |
1da177e4 | 151 | .Lonemb: |
25d83cbf | 152 | .int 0x100000 |
1da177e4 LT |
153 | |
154 | .Lfchunk: | |
1da177e4 LT |
155 | |
156 | # | |
157 | # find memory chunks. | |
158 | # | |
25d83cbf HC |
159 | lgr %r9,%r3 # end of mem |
160 | larl %r1,.Lchkmem # set program check address | |
161 | stg %r1,__LC_PGM_NEW_PSW+8 | |
162 | la %r1,1 # test in increments of 128KB | |
163 | sllg %r1,%r1,17 | |
164 | larl %r3,memory_chunk | |
165 | slgr %r4,%r4 # set start of chunk to zero | |
166 | slgr %r5,%r5 # set end of chunk to zero | |
167 | slr %r6,%r6 # set access code to zero | |
168 | la %r10,MEMORY_CHUNKS # number of chunks | |
1da177e4 | 169 | .Lloop: |
25d83cbf HC |
170 | tprot 0(%r5),0 # test protection of first byte |
171 | ipm %r7 | |
172 | srl %r7,28 | |
173 | clr %r6,%r7 # compare cc with last access code | |
174 | je .Lsame | |
dd401e2b HY |
175 | lghi %r8,0 # no program checks |
176 | j .Lsavchk | |
1da177e4 | 177 | .Lsame: |
25d83cbf HC |
178 | algr %r5,%r1 # add 128KB to end of chunk |
179 | # no need to check here, | |
180 | brc 12,.Lloop # this is the same chunk | |
181 | .Lchkmem: # > 16EB or tprot got a program check | |
dd401e2b HY |
182 | lghi %r8,1 # set program check flag |
183 | .Lsavchk: | |
25d83cbf HC |
184 | clgr %r4,%r5 # chunk size > 0? |
185 | je .Lchkloop | |
186 | stg %r4,0(%r3) # store start address of chunk | |
187 | lgr %r0,%r5 | |
188 | slgr %r0,%r4 | |
189 | stg %r0,8(%r3) # store size of chunk | |
190 | st %r6,20(%r3) # store type of chunk | |
191 | la %r3,24(%r3) | |
25d83cbf | 192 | ahi %r10,-1 # update chunk number |
1da177e4 | 193 | .Lchkloop: |
25d83cbf | 194 | lr %r6,%r7 # set access code to last cc |
1da177e4 LT |
195 | # we got an exception or we're starting a new |
196 | # chunk , we must check if we should | |
197 | # still try to find valid memory (if we detected | |
198 | # the amount of available storage), and if we | |
199 | # have chunks left | |
25d83cbf HC |
200 | lghi %r4,1 |
201 | sllg %r4,%r4,31 | |
202 | clgr %r5,%r4 | |
203 | je .Lhsaskip | |
204 | xr %r0, %r0 | |
205 | clgr %r0, %r9 # did we detect memory? | |
206 | je .Ldonemem # if not, leave | |
207 | chi %r10, 0 # do we have chunks left? | |
208 | je .Ldonemem | |
1da177e4 | 209 | .Lhsaskip: |
dd401e2b HY |
210 | chi %r8,1 # program check ? |
211 | je .Lpgmchk | |
212 | lgr %r4,%r5 # potential new chunk | |
213 | algr %r5,%r1 # add 128KB to end of chunk | |
214 | j .Llpcnt | |
215 | .Lpgmchk: | |
25d83cbf HC |
216 | algr %r5,%r1 # add 128KB to end of chunk |
217 | lgr %r4,%r5 # potential new chunk | |
dd401e2b | 218 | .Llpcnt: |
25d83cbf HC |
219 | clgr %r5,%r9 # should we go on? |
220 | jl .Lloop | |
221 | .Ldonemem: | |
1da177e4 | 222 | |
25d83cbf | 223 | larl %r12,machine_flags |
1da177e4 LT |
224 | # |
225 | # find out if we are running under VM | |
226 | # | |
25d83cbf HC |
227 | stidp __LC_CPUID # store cpuid |
228 | tm __LC_CPUID,0xff # running under VM ? | |
229 | bno 0f-.LPG1(%r13) | |
230 | oi 7(%r12),1 # set VM flag | |
231 | 0: lh %r0,__LC_CPUID+4 # get cpu version | |
232 | chi %r0,0x7490 # running on a P/390 ? | |
233 | bne 1f-.LPG1(%r13) | |
234 | oi 7(%r12),4 # set P/390 flag | |
1da177e4 LT |
235 | 1: |
236 | ||
237 | # | |
238 | # find out if we have the MVPG instruction | |
239 | # | |
25d83cbf HC |
240 | la %r1,0f-.LPG1(%r13) # set program check address |
241 | stg %r1,__LC_PGM_NEW_PSW+8 | |
242 | sgr %r0,%r0 | |
243 | lghi %r1,0 | |
244 | lghi %r2,0 | |
245 | mvpg %r1,%r2 # test MVPG instruction | |
246 | oi 7(%r12),16 # set MVPG flag | |
1da177e4 LT |
247 | 0: |
248 | ||
249 | # | |
250 | # find out if the diag 0x44 works in 64 bit mode | |
251 | # | |
25d83cbf HC |
252 | la %r1,0f-.LPG1(%r13) # set program check address |
253 | stg %r1,__LC_PGM_NEW_PSW+8 | |
254 | diag 0,0,0x44 # test diag 0x44 | |
255 | oi 7(%r12),32 # set diag44 flag | |
256 | 0: | |
1da177e4 LT |
257 | |
258 | # | |
259 | # find out if we have the IDTE instruction | |
260 | # | |
25d83cbf HC |
261 | la %r1,0f-.LPG1(%r13) # set program check address |
262 | stg %r1,__LC_PGM_NEW_PSW+8 | |
1da177e4 LT |
263 | .long 0xb2b10000 # store facility list |
264 | tm 0xc8,0x08 # check bit for clearing-by-ASCE | |
265 | bno 0f-.LPG1(%r13) | |
266 | lhi %r1,2094 | |
267 | lhi %r2,0 | |
268 | .long 0xb98e2001 | |
269 | oi 7(%r12),0x80 # set IDTE flag | |
270 | 0: | |
271 | ||
3c1fcfe2 MS |
272 | # |
273 | # find out if the diag 0x9c is available | |
274 | # | |
cb601d41 HC |
275 | la %r1,0f-.LPG1(%r13) # set program check address |
276 | stg %r1,__LC_PGM_NEW_PSW+8 | |
277 | stap __LC_CPUID+4 # store cpu address | |
278 | lh %r1,__LC_CPUID+4 | |
279 | diag %r1,0,0x9c # test diag 0x9c | |
280 | oi 6(%r12),1 # set diag9c flag | |
3c1fcfe2 MS |
281 | 0: |
282 | ||
6c2a9e6d GS |
283 | # |
284 | # find out if we have the MVCOS instruction | |
285 | # | |
286 | la %r1,0f-.LPG1(%r13) # set program check address | |
287 | stg %r1,__LC_PGM_NEW_PSW+8 | |
288 | .short 0xc800 # mvcos 0(%r0),0(%r0),%r0 | |
289 | .short 0x0000 | |
290 | .short 0x0000 | |
291 | 0: tm 0x8f,0x13 # special-operation exception? | |
292 | bno 1f-.LPG1(%r13) # if yes, MVCOS is present | |
293 | oi 6(%r12),2 # set MVCOS flag | |
294 | 1: | |
295 | ||
25d83cbf HC |
296 | lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, |
297 | # virtual and never return ... | |
298 | .align 16 | |
299 | .Lentry:.quad 0x0000000180000000,_stext | |
300 | .Lctl: .quad 0x04b50002 # cr0: various things | |
301 | .quad 0 # cr1: primary space segment table | |
302 | .quad .Lduct # cr2: dispatchable unit control table | |
303 | .quad 0 # cr3: instruction authorization | |
304 | .quad 0 # cr4: instruction authorization | |
305 | .quad 0xffffffffffffffff # cr5: primary-aste origin | |
306 | .quad 0 # cr6: I/O interrupts | |
307 | .quad 0 # cr7: secondary space segment table | |
308 | .quad 0 # cr8: access registers translation | |
309 | .quad 0 # cr9: tracing off | |
310 | .quad 0 # cr10: tracing off | |
311 | .quad 0 # cr11: tracing off | |
312 | .quad 0 # cr12: tracing off | |
313 | .quad 0 # cr13: home space segment table | |
314 | .quad 0xc0000000 # cr14: machine check handling off | |
315 | .quad 0 # cr15: linkage stack operations | |
316 | .Lduct: .long 0,0,0,0,0,0,0,0 | |
317 | .long 0,0,0,0,0,0,0,0 | |
318 | .Lpcmsk:.quad 0x0000000180000000 | |
1da177e4 | 319 | .L4malign:.quad 0xffffffffffc00000 |
25d83cbf HC |
320 | .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 |
321 | .Lnop: .long 0x07000700 | |
b1b70306 HC |
322 | .Lparmaddr: |
323 | .quad PARMAREA | |
1da177e4 | 324 | |
25d83cbf | 325 | .globl ipl_schib |
e87bfe51 HC |
326 | ipl_schib: |
327 | .rept 13 | |
328 | .long 0 | |
329 | .endr | |
330 | ||
25d83cbf | 331 | .globl ipl_flags |
e87bfe51 | 332 | ipl_flags: |
25d83cbf HC |
333 | .long 0 |
334 | .globl ipl_devno | |
e87bfe51 HC |
335 | ipl_devno: |
336 | .word 0 | |
337 | ||
dc8f5d21 | 338 | .org 0x12000 |
ff6b8ea6 MH |
339 | .globl s390_readinfo_sccb |
340 | s390_readinfo_sccb: | |
1da177e4 | 341 | .Lsccb: |
25d83cbf HC |
342 | .hword 0x1000 # length, one page |
343 | .byte 0x00,0x00,0x00 | |
344 | .byte 0x80 # variable response bit set | |
1da177e4 | 345 | .Lsccbr: |
25d83cbf | 346 | .hword 0x00 # response code |
1da177e4 | 347 | .Lscpincr1: |
25d83cbf | 348 | .hword 0x00 |
1da177e4 | 349 | .Lscpa1: |
25d83cbf HC |
350 | .byte 0x00 |
351 | .fill 89,1,0 | |
1da177e4 | 352 | .Lscpa2: |
25d83cbf | 353 | .int 0x00 |
1da177e4 | 354 | .Lscpincr2: |
25d83cbf HC |
355 | .quad 0x00 |
356 | .fill 3984,1,0 | |
dc8f5d21 | 357 | .org 0x13000 |
1e8e3383 | 358 | |
1da177e4 | 359 | #ifdef CONFIG_SHARED_KERNEL |
25d83cbf | 360 | .org 0x100000 |
1da177e4 | 361 | #endif |
25d83cbf | 362 | |
1da177e4 | 363 | # |
b1b70306 | 364 | # startup-code, running in absolute addressing mode |
1da177e4 | 365 | # |
25d83cbf HC |
366 | .globl _stext |
367 | _stext: basr %r13,0 # get base | |
1e8e3383 | 368 | .LPG3: |
1da177e4 | 369 | # check control registers |
25d83cbf HC |
370 | stctg %c0,%c15,0(%r15) |
371 | oi 6(%r15),0x40 # enable sigp emergency signal | |
372 | oi 4(%r15),0x10 # switch on low address proctection | |
373 | lctlg %c0,%c15,0(%r15) | |
1da177e4 | 374 | |
25d83cbf HC |
375 | lam 0,15,.Laregs-.LPG3(%r13) # load acrs needed by uaccess |
376 | brasl %r14,start_kernel # go to C code | |
1da177e4 LT |
377 | # |
378 | # We returned from start_kernel ?!? PANIK | |
379 | # | |
25d83cbf HC |
380 | basr %r13,0 |
381 | lpswe .Ldw-.(%r13) # load disabled wait psw | |
e87bfe51 | 382 | |
25d83cbf HC |
383 | .align 8 |
384 | .Ldw: .quad 0x0002000180000000,0x0000000000000000 | |
385 | .Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |