patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / s390 / kernel / head.S
1 /*
2  *  arch/s390/kernel/head.S
3  *
4  *  S390 version
5  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
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  *
10  * There are 5 different IPL methods
11  *  1) load the image directly into ram at address 0 and do an PSW restart
12  *  2) linload will load the image from address 0x10000 to memory 0x10000
13  *     and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
14  *  3) generate the tape ipl header, store the generated image on a tape
15  *     and ipl from it
16  *     In case of SL tape you need to IPL 5 times to get past VOL1 etc
17  *  4) generate the vm reader ipl header, move the generated image to the
18  *     VM reader (use option NOH!) and do a ipl from reader (VM only)
19  *  5) direct call of start by the SALIPL loader
20  *  We use the cpuid to distinguish between VM and native ipl
21  *  params for kernel are pushed to 0x10400 (see setup.h)
22
23     Changes: 
24     Okt 25 2000 <rvdheij@iae.nl>
25         added code to skip HDR and EOF to allow SL tape IPL (5 retries)
26         changed first CCW from rewind to backspace block
27
28  */
29
30 #include <linux/config.h>
31 #include <asm/setup.h>
32 #include <asm/lowcore.h>
33 #include <asm/offsets.h>
34
35 #ifndef CONFIG_IPL
36         .org   0
37         .long  0x00080000,0x80000000+startup   # Just a restart PSW
38 #else
39 #ifdef CONFIG_IPL_TAPE
40 #define IPL_BS 1024
41         .org   0
42         .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
43         .long  0x27000000,0x60000001           # by ipl to addresses 0-23.
44         .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
45         .long  0x00000000,0x00000000           # external old psw
46         .long  0x00000000,0x00000000           # svc old psw
47         .long  0x00000000,0x00000000           # program check old psw
48         .long  0x00000000,0x00000000           # machine check old psw
49         .long  0x00000000,0x00000000           # io old psw
50         .long  0x00000000,0x00000000
51         .long  0x00000000,0x00000000
52         .long  0x00000000,0x00000000
53         .long  0x000a0000,0x00000058           # external new psw
54         .long  0x000a0000,0x00000060           # svc new psw
55         .long  0x000a0000,0x00000068           # program check new psw
56         .long  0x000a0000,0x00000070           # machine check new psw
57         .long  0x00080000,0x80000000+.Lioint   # io new psw
58
59         .org   0x100
60 #
61 # subroutine for loading from tape
62 # Paramters:    
63 #  R1 = device number
64 #  R2 = load address
65 .Lloader:       
66         st    %r14,.Lldret
67         la    %r3,.Lorbread                    # r3 = address of orb 
68         la    %r5,.Lirb                        # r5 = address of irb
69         st    %r2,.Lccwread+4                  # initialize CCW data addresses
70         lctl  %c6,%c6,.Lcr6               
71         slr   %r2,%r2
72 .Lldlp:
73         la    %r6,3                            # 3 retries
74 .Lssch:
75         ssch  0(%r3)                           # load chunk of IPL_BS bytes
76         bnz   .Llderr
77 .Lw4end:
78         bas   %r14,.Lwait4io
79         tm    8(%r5),0x82                      # do we have a problem ?
80         bnz   .Lrecov
81         slr   %r7,%r7
82         icm   %r7,3,10(%r5)                    # get residual count
83         lcr   %r7,%r7
84         la    %r7,IPL_BS(%r7)                  # IPL_BS-residual=#bytes read
85         ar    %r2,%r7                          # add to total size
86         tm    8(%r5),0x01                      # found a tape mark ?
87         bnz   .Ldone
88         l     %r0,.Lccwread+4                  # update CCW data addresses
89         ar    %r0,%r7
90         st    %r0,.Lccwread+4                
91         b     .Lldlp
92 .Ldone:
93         l     %r14,.Lldret
94         br    %r14                             # r2 contains the total size
95 .Lrecov:
96         bas   %r14,.Lsense                     # do the sensing
97         bct   %r6,.Lssch                       # dec. retry count & branch
98         b     .Llderr
99 #
100 # Sense subroutine
101 #
102 .Lsense:
103         st    %r14,.Lsnsret
104         la    %r7,.Lorbsense              
105         ssch  0(%r7)                           # start sense command
106         bnz   .Llderr
107         bas   %r14,.Lwait4io
108         l     %r14,.Lsnsret
109         tm    8(%r5),0x82                      # do we have a problem ?
110         bnz   .Llderr
111         br    %r14
112 #
113 # Wait for interrupt subroutine
114 #
115 .Lwait4io:
116         lpsw  .Lwaitpsw                 
117 .Lioint:
118         c     %r1,0xb8                         # compare subchannel number
119         bne   .Lwait4io
120         tsch  0(%r5)
121         slr   %r0,%r0
122         tm    8(%r5),0x82                      # do we have a problem ?
123         bnz   .Lwtexit
124         tm    8(%r5),0x04                      # got device end ?
125         bz    .Lwait4io
126 .Lwtexit:
127         br    %r14
128 .Llderr:
129         lpsw  .Lcrash              
130
131         .align 8
132 .Lorbread:
133         .long  0x00000000,0x0080ff00,.Lccwread
134         .align 8
135 .Lorbsense:
136         .long  0x00000000,0x0080ff00,.Lccwsense
137         .align 8
138 .Lccwread:
139         .long  0x02200000+IPL_BS,0x00000000
140 .Lccwsense:
141         .long  0x04200001,0x00000000
142 .Lwaitpsw:
143         .long  0x020a0000,0x80000000+.Lioint
144
145 .Lirb:  .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
146 .Lcr6:  .long  0xff000000
147         .align 8
148 .Lcrash:.long  0x000a0000,0x00000000
149 .Lldret:.long  0
150 .Lsnsret: .long 0
151 #endif  /* CONFIG_IPL_TAPE */
152
153 #ifdef CONFIG_IPL_VM
154 #define IPL_BS 0x730
155         .org   0
156         .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
157         .long  0x02000018,0x60000050           # by ipl to addresses 0-23.
158         .long  0x02000068,0x60000050           # (a PSW and two CCWs).
159         .fill  80-24,1,0x40                    # bytes 24-79 are discarded !!
160         .long  0x020000f0,0x60000050           # The next 160 byte are loaded
161         .long  0x02000140,0x60000050           # to addresses 0x18-0xb7
162         .long  0x02000190,0x60000050           # They form the continuation
163         .long  0x020001e0,0x60000050           # of the CCW program started
164         .long  0x02000230,0x60000050           # by ipl and load the range
165         .long  0x02000280,0x60000050           # 0x0f0-0x730 from the image
166         .long  0x020002d0,0x60000050           # to the range 0x0f0-0x730
167         .long  0x02000320,0x60000050           # in memory. At the end of
168         .long  0x02000370,0x60000050           # the channel program the PSW
169         .long  0x020003c0,0x60000050           # at location 0 is loaded.
170         .long  0x02000410,0x60000050           # Initial processing starts
171         .long  0x02000460,0x60000050           # at 0xf0 = iplstart.
172         .long  0x020004b0,0x60000050
173         .long  0x02000500,0x60000050
174         .long  0x02000550,0x60000050
175         .long  0x020005a0,0x60000050
176         .long  0x020005f0,0x60000050
177         .long  0x02000640,0x60000050
178         .long  0x02000690,0x60000050
179         .long  0x020006e0,0x20000050
180
181         .org   0xf0
182 #
183 # subroutine for loading cards from the reader
184 #
185 .Lloader:       
186         la    %r3,.Lorb                        # r2 = address of orb into r2
187         la    %r5,.Lirb                        # r4 = address of irb
188         la    %r6,.Lccws              
189         la    %r7,20
190 .Linit:
191         st    %r2,4(%r6)                       # initialize CCW data addresses
192         la    %r2,0x50(%r2)
193         la    %r6,8(%r6)
194         bct   7,.Linit
195
196         lctl  %c6,%c6,.Lcr6                    # set IO subclass mask
197         slr   %r2,%r2
198 .Lldlp:
199         ssch  0(%r3)                           # load chunk of 1600 bytes
200         bnz   .Llderr
201 .Lwait4irq:
202         mvc   __LC_IO_NEW_PSW(8),.Lnewpsw      # set up IO interrupt psw
203         lpsw  .Lwaitpsw              
204 .Lioint:
205         c     %r1,0xb8                         # compare subchannel number
206         bne   .Lwait4irq
207         tsch  0(%r5)
208
209         slr   %r0,%r0
210         ic    %r0,8(%r5)                       # get device status
211         chi   %r0,8                            # channel end ?
212         be    .Lcont
213         chi   %r0,12                           # channel end + device end ?
214         be    .Lcont
215
216         l     %r0,4(%r5)
217         s     %r0,8(%r3)                       # r0/8 = number of ccws executed
218         mhi   %r0,10                           # *10 = number of bytes in ccws
219         lh    %r3,10(%r5)                      # get residual count
220         sr    %r0,%r3                          # #ccws*80-residual=#bytes read
221         ar    %r2,%r0
222         
223         br    %r14                             # r2 contains the total size
224
225 .Lcont:
226         ahi   %r2,0x640                        # add 0x640 to total size
227         la    %r6,.Lccws             
228         la    %r7,20
229 .Lincr:
230         l     %r0,4(%r6)                       # update CCW data addresses
231         ahi   %r0,0x640
232         st    %r0,4(%r6)
233         ahi   %r6,8
234         bct   7,.Lincr
235
236         b     .Lldlp
237 .Llderr:
238         lpsw  .Lcrash              
239
240         .align 8
241 .Lorb:  .long  0x00000000,0x0080ff00,.Lccws
242 .Lirb:  .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
243 .Lcr6:  .long  0xff000000
244 .Lloadp:.long  0,0
245         .align 8
246 .Lcrash:.long  0x000a0000,0x00000000
247 .Lnewpsw:
248         .long  0x00080000,0x80000000+.Lioint
249 .Lwaitpsw:
250         .long  0x020a0000,0x80000000+.Lioint
251
252         .align 8
253 .Lccws: .rept  19
254         .long  0x02600050,0x00000000
255         .endr
256         .long  0x02200050,0x00000000
257 #endif  /* CONFIG_IPL_VM */
258
259 iplstart:
260         lh    %r1,0xb8                         # test if subchannel number
261         bct   %r1,.Lnoload                     #  is valid
262         l     %r1,0xb8                         # load ipl subchannel number
263         la    %r2,IPL_BS                       # load start address
264         bas   %r14,.Lloader                    # load rest of ipl image
265         l     %r12,.Lparm                      # pointer to parameter area
266         st    %r1,IPL_DEVICE-PARMAREA(%r12)    # store ipl device number
267
268 #
269 # load parameter file from ipl device
270 #
271 .Lagain1:
272         l     %r2,INITRD_START-PARMAREA(%r12)  # use ramdisk location as temp
273         bas   %r14,.Lloader                    # load parameter file
274         ltr   %r2,%r2                          # got anything ?
275         bz    .Lnopf
276         chi   %r2,895
277         bnh   .Lnotrunc
278         la    %r2,895
279 .Lnotrunc:
280         l     %r4,INITRD_START-PARMAREA(%r12)
281         clc   0(3,%r4),.L_hdr                  # if it is HDRx
282         bz    .Lagain1                         # skip dataset header
283         clc   0(3,%r4),.L_eof                  # if it is EOFx
284         bz    .Lagain1                         # skip dateset trailer
285         la    %r5,0(%r4,%r2)
286         lr    %r3,%r2
287 .Lidebc:
288         tm    0(%r5),0x80                      # high order bit set ?
289         bo    .Ldocv                           #  yes -> convert from EBCDIC
290         ahi   %r5,-1
291         bct   %r3,.Lidebc
292         b     .Lnocv
293 .Ldocv:
294         l     %r3,.Lcvtab
295         tr    0(256,%r4),0(%r3)                # convert parameters to ascii
296         tr    256(256,%r4),0(%r3)
297         tr    512(256,%r4),0(%r3)
298         tr    768(122,%r4),0(%r3)
299 .Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
300         mvc   0(256,%r3),0(%r4)
301         mvc   256(256,%r3),256(%r4)
302         mvc   512(256,%r3),512(%r4)
303         mvc   768(122,%r3),768(%r4)
304         slr   %r0,%r0
305         b     .Lcntlp
306 .Ldelspc:
307         ic    %r0,0(%r2,%r3)
308         chi   %r0,0x20                         # is it a space ?
309         be    .Lcntlp
310         ahi   %r2,1
311         b     .Leolp
312 .Lcntlp:
313         brct  %r2,.Ldelspc
314 .Leolp:
315         slr   %r0,%r0
316         stc   %r0,0(%r2,%r3)                   # terminate buffer
317 .Lnopf:
318
319 #
320 # load ramdisk from ipl device
321 #       
322 .Lagain2:
323         l     %r2,INITRD_START-PARMAREA(%r12)  # load adr. of ramdisk
324         bas   %r14,.Lloader                    # load ramdisk
325         st    %r2,INITRD_SIZE-PARMAREA(%r12)   # store size of ramdisk
326         ltr   %r2,%r2
327         bnz   .Lrdcont
328         st    %r2,INITRD_START-PARMAREA(%r12)  # no ramdisk found, null it
329 .Lrdcont:
330         l     %r2,INITRD_START-PARMAREA(%r12)
331
332         clc   0(3,%r2),.L_hdr                  # skip HDRx and EOFx 
333         bz    .Lagain2
334         clc   0(3,%r2),.L_eof
335         bz    .Lagain2
336
337 #ifdef CONFIG_IPL_VM
338 #
339 # reset files in VM reader
340 #
341         stidp __LC_CPUID                       # store cpuid
342         tm    __LC_CPUID,0xff                  # running VM ?
343         bno   .Lnoreset
344         la    %r2,.Lreset              
345         lhi   %r3,26
346         .long 0x83230008
347 .Lnoreset:
348 #endif
349         
350 #
351 # everything loaded, go for it
352 #
353 .Lnoload:
354         l     %r1,.Lstartup
355         br    %r1
356
357 .Lparm: .long  PARMAREA
358 .Lstartup: .long startup
359 .Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
360 .Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
361         .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
362         .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
363 .L_eof: .long  0xc5d6c600       /* C'EOF' */
364 .L_hdr: .long  0xc8c4d900       /* C'HDR' */
365
366 #endif  /* CONFIG_IPL */
367
368 #
369 # SALIPL loader support. Based on a patch by Rob van der Heij.
370 # This entry point is called directly from the SALIPL loader and
371 # doesn't need a builtin ipl record.
372 #
373         .org  0x800
374         .globl start
375 start:
376         stm   %r0,%r15,0x07b0           # store registers
377         basr  %r12,%r0
378 .base:
379         l     %r11,.parm
380         l     %r8,.cmd                  # pointer to command buffer
381
382         ltr   %r9,%r9                   # do we have SALIPL parameters?
383         bp    .sk8x8
384
385         mvc   0(64,%r8),0x00b0          # copy saved registers
386         xc    64(240-64,%r8),0(%r8)     # remainder of buffer
387         tr    0(64,%r8),.lowcase        
388         b     .gotr
389 .sk8x8:
390         mvc   0(240,%r8),0(%r9)         # copy iplparms into buffer
391 .gotr:
392         l     %r10,.tbl                 # EBCDIC to ASCII table
393         tr    0(240,%r8),0(%r10)
394         stidp __LC_CPUID                # Are we running on VM maybe
395         cli   __LC_CPUID,0xff
396         bnz   .test
397         .long 0x83300060                # diag 3,0,x'0060' - storage size
398         b     .done
399 .test:
400         mvc   0x68(8),.pgmnw            # set up pgm check handler
401         l     %r2,.fourmeg
402         lr    %r3,%r2
403         bctr  %r3,%r0                   # 4M-1
404 .loop:  iske  %r0,%r3
405         ar    %r3,%r2
406 .pgmx:
407         sr    %r3,%r2
408         la    %r3,1(%r3)
409 .done:
410         l     %r1,.memsize
411         st    %r3,0(%r1)
412         slr   %r0,%r0
413         st    %r0,INITRD_SIZE-PARMAREA(%r11)
414         st    %r0,INITRD_START-PARMAREA(%r11)
415         j     startup                   # continue with startup
416 .tbl:   .long _ebcasc                   # translate table
417 .cmd:   .long COMMAND_LINE              # address of command line buffer
418 .parm:  .long PARMAREA
419 .memsize: .long memory_size
420 .fourmeg: .long 0x00400000              # 4M
421 .pgmnw: .long 0x00080000,.pgmx
422 .lowcase:
423         .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 
424         .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
425         .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 
426         .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
427         .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 
428         .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
429         .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 
430         .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
431         .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 
432         .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
433         .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 
434         .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
435         .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 
436         .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
437         .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 
438         .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
439
440         .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 
441         .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
442         .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 
443         .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
444         .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 
445         .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
446         .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 
447         .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
448         .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87   # .abcdefg 
449         .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf   # hi
450         .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97   # .jklmnop
451         .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf   # qr
452         .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7   # ..stuvwx
453         .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef   # yz
454         .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
455         .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
456
457 #
458 # startup-code at 0x10000, running in real mode
459 # this is called either by the ipl loader or directly by PSW restart
460 # or linload or SALIPL
461 #
462         .org  0x10000
463 startup:basr  %r13,0                     # get base
464 .LPG1:  lctl  %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
465         la    %r12,_pstart-.LPG1(%r13)   # pointer to parameter area
466                                          # move IPL device to lowcore
467         mvc   __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
468         
469 #
470 # clear bss memory
471 #
472         l     %r2,.Lbss_bgn-.LPG1(%r13) # start of bss
473         l     %r3,.Lbss_end-.LPG1(%r13) # end of bss
474         sr    %r3,%r2                   # length of bss
475         sr    %r4,%r4                   #
476         sr    %r5,%r5                   # set src,length and pad to zero
477         sr    %r0,%r0                   #
478         mvcle %r2,%r4,0                 # clear mem
479         jo    .-4                       # branch back, if not finish
480
481         l     %r2,.Lrcp-.LPG1(%r13)     # Read SCP forced command word
482 .Lservicecall:
483         stosm .Lpmask-.LPG1(%r13),0x01  # authorize ext interrupts
484
485         stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0
486         la    %r1,0x200                 # set bit 22
487         o     %r1,.Lcr-.LPG1(%r13)      # or old cr0 with r1
488         st    %r1,.Lcr-.LPG1(%r13)
489         lctl  %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0
490
491         mvc   __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
492         la    %r1, .Lsclph-.LPG1(%r13)
493         a     %r1,__LC_EXT_NEW_PSW+4    # set handler
494         st    %r1,__LC_EXT_NEW_PSW+4
495
496         la    %r4,_pstart-.LPG1(%r13)   # %r4 is our index for sccb stuff
497         la    %r1, .Lsccb-PARMAREA(%r4) # our sccb
498         .insn rre,0xb2200000,%r2,%r1    # service call
499         ipm   %r1
500         srl   %r1,28                    # get cc code
501         xr    %r3, %r3
502         chi   %r1,3
503         be    .Lfchunk-.LPG1(%r13)      # leave
504         chi   %r1,2
505         be    .Lservicecall-.LPG1(%r13)
506         lpsw  .Lwaitsclp-.LPG1(%r13)
507 .Lsclph:
508         lh    %r1,.Lsccbr-PARMAREA(%r4)
509         chi   %r1,0x10                  # 0x0010 is the sucess code
510         je    .Lprocsccb                # let's process the sccb
511         chi   %r1,0x1f0
512         bne   .Lfchunk-.LPG1(%r13)      # unhandled error code
513         c     %r2, .Lrcp-.LPG1(%r13)    # Did we try Read SCP forced
514         bne   .Lfchunk-.LPG1(%r13)      # if no, give up
515         l     %r2, .Lrcp2-.LPG1(%r13)   # try with Read SCP
516         b     .Lservicecall-.LPG1(%r13)
517 .Lprocsccb:
518         lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
519         chi   %r1,0x00
520         jne   .Lscnd
521         l     %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
522 .Lscnd:
523         xr    %r3,%r3                   # same logic
524         ic    %r3,.Lscpa1-PARMAREA(%r4)
525         chi   %r3,0x00
526         jne   .Lcompmem
527         l     %r3,.Lscpa2-PARMAREA(%r13)
528 .Lcompmem:
529         mr    %r2,%r1                   # mem in MB on 128-bit
530         l     %r1,.Lonemb-.LPG1(%r13)
531         mr    %r2,%r1                   # mem size in bytes in %r3
532         b     .Lfchunk-.LPG1(%r13)
533
534 .Lpmask:
535         .byte 0
536 .align 8
537 .Lpcext:.long  0x00080000,0x80000000
538 .Lcr:
539         .long 0x00                      # place holder for cr0
540 .Lwaitsclp:
541         .long 0x020A0000
542         .long .Lsclph
543 .Lrcp:
544         .int 0x00120001                 # Read SCP forced code
545 .Lrcp2:
546         .int 0x00020001                 # Read SCP code
547 .Lonemb:
548         .int 0x100000
549 .Lfchunk:
550
551 #
552 # find memory chunks.
553 #
554         lr    %r9,%r3                    # end of mem
555         mvc   __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
556         la    %r1,1                      # test in increments of 128KB
557         sll   %r1,17
558         l     %r3,.Lmchunk-.LPG1(%r13)   # get pointer to memory_chunk array
559         slr   %r4,%r4                    # set start of chunk to zero
560         slr   %r5,%r5                    # set end of chunk to zero
561         slr   %r6,%r6                    # set access code to zero
562         la    %r10, MEMORY_CHUNKS        # number of chunks
563 .Lloop:
564         tprot 0(%r5),0                   # test protection of first byte
565         ipm   %r7
566         srl   %r7,28
567         clr   %r6,%r7                    # compare cc with last access code
568         be    .Lsame-.LPG1(%r13)
569         b     .Lchkmem-.LPG1(%r13)
570 .Lsame:
571         ar    %r5,%r1                    # add 128KB to end of chunk
572         bno   .Lloop-.LPG1(%r13)         # r1 < 0x80000000 -> loop
573 .Lchkmem:                                # > 2GB or tprot got a program check
574         clr   %r4,%r5                    # chunk size > 0?
575         be    .Lchkloop-.LPG1(%r13)
576         st    %r4,0(%r3)                 # store start address of chunk
577         lr    %r0,%r5
578         slr   %r0,%r4
579         st    %r0,4(%r3)                 # store size of chunk
580         st    %r6,8(%r3)                 # store type of chunk
581         la    %r3,12(%r3)
582         l     %r4,.Lmemsize-.LPG1(%r13)  # address of variable memory_size
583         st    %r5,0(%r4)                 # store last end to memory size
584         ahi   %r10,-1                    # update chunk number
585 .Lchkloop:
586         lr    %r6,%r7                    # set access code to last cc
587         # we got an exception or we're starting a new
588         # chunk , we must check if we should
589         # still try to find valid memory (if we detected
590         # the amount of available storage), and if we
591         # have chunks left
592         xr    %r0,%r0
593         clr   %r0,%r9                    # did we detect memory?
594         je    .Ldonemem                  # if not, leave
595         chi   %r10,0                     # do we have chunks left?
596         je    .Ldonemem
597         alr   %r5,%r1                    # add 128KB to end of chunk
598         lr    %r4,%r5                    # potential new chunk
599         clr    %r5,%r9                   # should we go on?
600         jl     .Lloop
601 .Ldonemem:              
602         l      %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
603 #
604 # find out if we are running under VM
605 #
606         stidp  __LC_CPUID               # store cpuid
607         tm     __LC_CPUID,0xff          # running under VM ?
608         bno    .Lnovm-.LPG1(%r13)
609         oi     3(%r12),1                # set VM flag
610 .Lnovm:
611         lh     %r0,__LC_CPUID+4         # get cpu version
612         chi    %r0,0x7490               # running on a P/390 ?
613         bne    .Lnop390-.LPG1(%r13)
614         oi     3(%r12),4                # set P/390 flag
615 .Lnop390:
616         chi    %r0,0x2084               # new stidp format?
617         bne    .Loldfmt-.LPG1(%r13)
618         oi     3(%r12),64               # set new stidp flag
619 .Loldfmt:       
620
621 #
622 # find out if we have an IEEE fpu
623 #
624         mvc    __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
625         efpc   %r0,0                    # test IEEE extract fpc instruction
626         oi     3(%r12),2                # set IEEE fpu flag
627 .Lchkfpu:
628
629 #
630 # find out if we have the CSP instruction
631 #
632        mvc    __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
633        la     %r0,0
634        lr     %r1,%r0
635        la     %r2,4
636        csp    %r0,%r2                   # Test CSP instruction
637        oi     3(%r12),8                 # set CSP flag
638 .Lchkcsp:
639
640 #
641 # find out if we have the MVPG instruction
642 #
643        mvc    __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
644        sr     %r0,%r0
645        la     %r1,0
646        la     %r2,0
647        mvpg   %r1,%r2                   # Test CSP instruction
648        oi     3(%r12),16                # set MVPG flag
649 .Lchkmvpg:
650
651 #
652 # find out if we have the IDTE instruction
653 #
654         mvc     __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
655         .long   0xb2b10000              # store facility list
656         tm      0xc8,0x08               # check bit for clearing-by-ASCE
657         bno     .Lchkidte-.LPG1(%r13)
658         lhi     %r1,2094
659         lhi     %r2,0
660         .long   0xb98e2001
661         oi      3(%r12),0x80            # set IDTE flag
662 .Lchkidte:
663
664         lpsw  .Lentry-.LPG1(13)         # jump to _stext in primary-space,
665                                         # virtual and never return ...
666         .align 8
667 .Lentry:.long  0x00080000,0x80000000 + _stext
668 .Lctl:  .long  0x04b50002               # cr0: various things
669         .long  0                        # cr1: primary space segment table
670         .long  .Lduct                   # cr2: dispatchable unit control table
671         .long  0                        # cr3: instruction authorization
672         .long  0                        # cr4: instruction authorization
673         .long  0xffffffff               # cr5: primary-aste origin
674         .long  0                        # cr6:  I/O interrupts
675         .long  0                        # cr7:  secondary space segment table
676         .long  0                        # cr8:  access registers translation
677         .long  0                        # cr9:  tracing off
678         .long  0                        # cr10: tracing off
679         .long  0                        # cr11: tracing off
680         .long  0                        # cr12: tracing off
681         .long  0                        # cr13: home space segment table
682         .long  0xc0000000               # cr14: machine check handling off
683         .long  0                        # cr15: linkage stack operations
684 .Lpcmem:.long  0x00080000,0x80000000 + .Lchkmem
685 .Lpcfpu:.long  0x00080000,0x80000000 + .Lchkfpu
686 .Lpccsp:.long  0x00080000,0x80000000 + .Lchkcsp
687 .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
688 .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
689 .Lmemsize:.long memory_size
690 .Lmchunk:.long memory_chunk
691 .Lmflags:.long machine_flags
692 .Lbss_bgn:  .long  __bss_start
693 .Lbss_end:  .long  _end
694
695         .org PARMAREA-64
696 .Lduct: .long 0,0,0,0,0,0,0,0
697         .long 0,0,0,0,0,0,0,0
698
699 #
700 # params at 10400 (setup.h)
701 #
702         .org   PARMAREA
703         .global _pstart
704 _pstart:        
705         .long  0,0                      # IPL_DEVICE
706         .long  0,RAMDISK_ORIGIN         # INITRD_START
707         .long  0,RAMDISK_SIZE           # INITRD_SIZE
708
709         .org   COMMAND_LINE
710         .byte  "root=/dev/ram0 ro"
711         .byte  0
712         .org   0x11000
713 .Lsccb:
714         .hword 0x1000                   # length, one page
715         .byte 0x00,0x00,0x00
716         .byte 0x80                      # variable response bit set
717 .Lsccbr:
718         .hword 0x00                     # response code
719 .Lscpincr1:
720         .hword 0x00
721 .Lscpa1:
722         .byte 0x00
723         .fill 89,1,0
724 .Lscpa2:
725         .int 0x00
726 .Lscpincr2:
727         .quad 0x00
728         .fill 3984,1,0
729         .org 0x12000
730         .global _pend
731 _pend:  
732
733 #ifdef CONFIG_SHARED_KERNEL
734         .org   0x100000
735 #endif
736
737 #
738 # startup-code, running in virtual mode
739 #
740         .globl _stext
741 _stext: basr  %r13,0                    # get base
742 .LPG2:
743 #
744 # Setup stack
745 #
746         l     %r15,.Linittu-.LPG2(%r13)
747         mvc   __LC_CURRENT(4),__TI_task(%r15)
748         ahi   %r15,8192                 # init_task_union + 8192
749         st    %r15,__LC_KERNEL_STACK    # set end of kernel stack
750         ahi   %r15,-96
751         xc    0(4,%r15),0(%r15)         # set backchain to zero
752
753 # check control registers
754         stctl  %c0,%c15,0(%r15)
755         oi     2(%r15),0x20             # enable sigp external interrupts
756         oi     0(%r15),0x10             # switch on low address protection
757         lctl   %c0,%c15,0(%r15)
758
759 #
760         lam    0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess
761         l      %r14,.Lstart-.LPG2(%r13)
762         basr   %r14,%r14                # call start_kernel
763 #
764 # We returned from start_kernel ?!? PANIK
765 #
766         basr  %r13,0
767         lpsw  .Ldw-.(%r13)           # load disabled wait psw
768 #
769             .align 8
770 .Ldw:       .long  0x000a0000,0x00000000
771 .Linittu:   .long  init_thread_union
772 .Lstart:    .long  start_kernel
773 .Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
774