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