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