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