xref: /OK3568_Linux_fs/kernel/arch/s390/boot/head.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun/*
3*4882a593Smuzhiyun * Copyright IBM Corp. 1999, 2010
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun *    Author(s): Hartmut Penner <hp@de.ibm.com>
6*4882a593Smuzhiyun *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
7*4882a593Smuzhiyun *		 Rob van der Heij <rvdhei@iae.nl>
8*4882a593Smuzhiyun *		 Heiko Carstens <heiko.carstens@de.ibm.com>
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * There are 5 different IPL methods
11*4882a593Smuzhiyun *  1) load the image directly into ram at address 0 and do an PSW restart
12*4882a593Smuzhiyun *  2) linload will load the image from address 0x10000 to memory 0x10000
13*4882a593Smuzhiyun *     and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
14*4882a593Smuzhiyun *  3) generate the tape ipl header, store the generated image on a tape
15*4882a593Smuzhiyun *     and ipl from it
16*4882a593Smuzhiyun *     In case of SL tape you need to IPL 5 times to get past VOL1 etc
17*4882a593Smuzhiyun *  4) generate the vm reader ipl header, move the generated image to the
18*4882a593Smuzhiyun *     VM reader (use option NOH!) and do a ipl from reader (VM only)
19*4882a593Smuzhiyun *  5) direct call of start by the SALIPL loader
20*4882a593Smuzhiyun *  We use the cpuid to distinguish between VM and native ipl
21*4882a593Smuzhiyun *  params for kernel are pushed to 0x10400 (see setup.h)
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun#include <linux/init.h>
26*4882a593Smuzhiyun#include <linux/linkage.h>
27*4882a593Smuzhiyun#include <asm/asm-offsets.h>
28*4882a593Smuzhiyun#include <asm/thread_info.h>
29*4882a593Smuzhiyun#include <asm/page.h>
30*4882a593Smuzhiyun#include <asm/ptrace.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun#define ARCH_OFFSET	4
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun__HEAD
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun#define IPL_BS	0x730
37*4882a593Smuzhiyun	.org	0
38*4882a593Smuzhiyun	.long	0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
39*4882a593Smuzhiyun	.long	0x02000018,0x60000050		# by ipl to addresses 0-23.
40*4882a593Smuzhiyun	.long	0x02000068,0x60000050		# (a PSW and two CCWs).
41*4882a593Smuzhiyun	.fill	80-24,1,0x40			# bytes 24-79 are discarded !!
42*4882a593Smuzhiyun	.long	0x020000f0,0x60000050		# The next 160 byte are loaded
43*4882a593Smuzhiyun	.long	0x02000140,0x60000050		# to addresses 0x18-0xb7
44*4882a593Smuzhiyun	.long	0x02000190,0x60000050		# They form the continuation
45*4882a593Smuzhiyun	.long	0x020001e0,0x60000050		# of the CCW program started
46*4882a593Smuzhiyun	.long	0x02000230,0x60000050		# by ipl and load the range
47*4882a593Smuzhiyun	.long	0x02000280,0x60000050		# 0x0f0-0x730 from the image
48*4882a593Smuzhiyun	.long	0x020002d0,0x60000050		# to the range 0x0f0-0x730
49*4882a593Smuzhiyun	.long	0x02000320,0x60000050		# in memory. At the end of
50*4882a593Smuzhiyun	.long	0x02000370,0x60000050		# the channel program the PSW
51*4882a593Smuzhiyun	.long	0x020003c0,0x60000050		# at location 0 is loaded.
52*4882a593Smuzhiyun	.long	0x02000410,0x60000050		# Initial processing starts
53*4882a593Smuzhiyun	.long	0x02000460,0x60000050		# at 0x200 = iplstart.
54*4882a593Smuzhiyun	.long	0x020004b0,0x60000050
55*4882a593Smuzhiyun	.long	0x02000500,0x60000050
56*4882a593Smuzhiyun	.long	0x02000550,0x60000050
57*4882a593Smuzhiyun	.long	0x020005a0,0x60000050
58*4882a593Smuzhiyun	.long	0x020005f0,0x60000050
59*4882a593Smuzhiyun	.long	0x02000640,0x60000050
60*4882a593Smuzhiyun	.long	0x02000690,0x60000050
61*4882a593Smuzhiyun	.long	0x020006e0,0x20000050
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun	.org	__LC_RST_NEW_PSW		# 0x1a0
64*4882a593Smuzhiyun	.quad	0,iplstart
65*4882a593Smuzhiyun	.org	__LC_PGM_NEW_PSW		# 0x1d0
66*4882a593Smuzhiyun	.quad	0x0000000180000000,startup_pgm_check_handler
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun	.org	0x200
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun#
71*4882a593Smuzhiyun# subroutine to wait for end I/O
72*4882a593Smuzhiyun#
73*4882a593Smuzhiyun.Lirqwait:
74*4882a593Smuzhiyun	mvc	__LC_IO_NEW_PSW(16),.Lnewpsw	# set up IO interrupt psw
75*4882a593Smuzhiyun	lpsw	.Lwaitpsw
76*4882a593Smuzhiyun.Lioint:
77*4882a593Smuzhiyun	br	%r14
78*4882a593Smuzhiyun	.align	8
79*4882a593Smuzhiyun.Lnewpsw:
80*4882a593Smuzhiyun	.quad	0x0000000080000000,.Lioint
81*4882a593Smuzhiyun.Lwaitpsw:
82*4882a593Smuzhiyun	.long	0x020a0000,0x80000000+.Lioint
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun#
85*4882a593Smuzhiyun# subroutine for loading cards from the reader
86*4882a593Smuzhiyun#
87*4882a593Smuzhiyun.Lloader:
88*4882a593Smuzhiyun	la	%r4,0(%r14)
89*4882a593Smuzhiyun	la	%r3,.Lorb		# r2 = address of orb into r2
90*4882a593Smuzhiyun	la	%r5,.Lirb		# r4 = address of irb
91*4882a593Smuzhiyun	la	%r6,.Lccws
92*4882a593Smuzhiyun	la	%r7,20
93*4882a593Smuzhiyun.Linit:
94*4882a593Smuzhiyun	st	%r2,4(%r6)		# initialize CCW data addresses
95*4882a593Smuzhiyun	la	%r2,0x50(%r2)
96*4882a593Smuzhiyun	la	%r6,8(%r6)
97*4882a593Smuzhiyun	bct	7,.Linit
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun	lctl	%c6,%c6,.Lcr6		# set IO subclass mask
100*4882a593Smuzhiyun	slr	%r2,%r2
101*4882a593Smuzhiyun.Lldlp:
102*4882a593Smuzhiyun	ssch	0(%r3)			# load chunk of 1600 bytes
103*4882a593Smuzhiyun	bnz	.Llderr
104*4882a593Smuzhiyun.Lwait4irq:
105*4882a593Smuzhiyun	bas	%r14,.Lirqwait
106*4882a593Smuzhiyun	c	%r1,__LC_SUBCHANNEL_ID	# compare subchannel number
107*4882a593Smuzhiyun	bne	.Lwait4irq
108*4882a593Smuzhiyun	tsch	0(%r5)
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun	slr	%r0,%r0
111*4882a593Smuzhiyun	ic	%r0,8(%r5)		# get device status
112*4882a593Smuzhiyun	chi	%r0,8			# channel end ?
113*4882a593Smuzhiyun	be	.Lcont
114*4882a593Smuzhiyun	chi	%r0,12			# channel end + device end ?
115*4882a593Smuzhiyun	be	.Lcont
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun	l	%r0,4(%r5)
118*4882a593Smuzhiyun	s	%r0,8(%r3)		# r0/8 = number of ccws executed
119*4882a593Smuzhiyun	mhi	%r0,10			# *10 = number of bytes in ccws
120*4882a593Smuzhiyun	lh	%r3,10(%r5)		# get residual count
121*4882a593Smuzhiyun	sr	%r0,%r3 		# #ccws*80-residual=#bytes read
122*4882a593Smuzhiyun	ar	%r2,%r0
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun	br	%r4			# r2 contains the total size
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun.Lcont:
127*4882a593Smuzhiyun	ahi	%r2,0x640		# add 0x640 to total size
128*4882a593Smuzhiyun	la	%r6,.Lccws
129*4882a593Smuzhiyun	la	%r7,20
130*4882a593Smuzhiyun.Lincr:
131*4882a593Smuzhiyun	l	%r0,4(%r6)		# update CCW data addresses
132*4882a593Smuzhiyun	ahi	%r0,0x640
133*4882a593Smuzhiyun	st	%r0,4(%r6)
134*4882a593Smuzhiyun	ahi	%r6,8
135*4882a593Smuzhiyun	bct	7,.Lincr
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun	b	.Lldlp
138*4882a593Smuzhiyun.Llderr:
139*4882a593Smuzhiyun	lpsw	.Lcrash
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun	.align	8
142*4882a593Smuzhiyun.Lorb:	.long	0x00000000,0x0080ff00,.Lccws
143*4882a593Smuzhiyun.Lirb:	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
144*4882a593Smuzhiyun.Lcr6:	.long	0xff000000
145*4882a593Smuzhiyun.Lloadp:.long	0,0
146*4882a593Smuzhiyun	.align	8
147*4882a593Smuzhiyun.Lcrash:.long	0x000a0000,0x00000000
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun	.align	8
150*4882a593Smuzhiyun.Lccws: .rept	19
151*4882a593Smuzhiyun	.long	0x02600050,0x00000000
152*4882a593Smuzhiyun	.endr
153*4882a593Smuzhiyun	.long	0x02200050,0x00000000
154*4882a593Smuzhiyun
155*4882a593Smuzhiyuniplstart:
156*4882a593Smuzhiyun	mvi	__LC_AR_MODE_ID,1	# set esame flag
157*4882a593Smuzhiyun	slr	%r0,%r0			# set cpuid to zero
158*4882a593Smuzhiyun	lhi	%r1,2			# mode 2 = esame (dump)
159*4882a593Smuzhiyun	sigp	%r1,%r0,0x12		# switch to esame mode
160*4882a593Smuzhiyun	bras	%r13,0f
161*4882a593Smuzhiyun	.fill	16,4,0x0
162*4882a593Smuzhiyun0:	lmh	%r0,%r15,0(%r13)	# clear high-order half of gprs
163*4882a593Smuzhiyun	sam31				# switch to 31 bit addressing mode
164*4882a593Smuzhiyun	lh	%r1,__LC_SUBCHANNEL_ID	# test if subchannel number
165*4882a593Smuzhiyun	bct	%r1,.Lnoload		#  is valid
166*4882a593Smuzhiyun	l	%r1,__LC_SUBCHANNEL_ID	# load ipl subchannel number
167*4882a593Smuzhiyun	la	%r2,IPL_BS		# load start address
168*4882a593Smuzhiyun	bas	%r14,.Lloader		# load rest of ipl image
169*4882a593Smuzhiyun	l	%r12,.Lparm		# pointer to parameter area
170*4882a593Smuzhiyun	st	%r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun#
173*4882a593Smuzhiyun# load parameter file from ipl device
174*4882a593Smuzhiyun#
175*4882a593Smuzhiyun.Lagain1:
176*4882a593Smuzhiyun	l	%r2,.Linitrd		# ramdisk loc. is temp
177*4882a593Smuzhiyun	bas	%r14,.Lloader		# load parameter file
178*4882a593Smuzhiyun	ltr	%r2,%r2 		# got anything ?
179*4882a593Smuzhiyun	bz	.Lnopf
180*4882a593Smuzhiyun	chi	%r2,895
181*4882a593Smuzhiyun	bnh	.Lnotrunc
182*4882a593Smuzhiyun	la	%r2,895
183*4882a593Smuzhiyun.Lnotrunc:
184*4882a593Smuzhiyun	l	%r4,.Linitrd
185*4882a593Smuzhiyun	clc	0(3,%r4),.L_hdr		# if it is HDRx
186*4882a593Smuzhiyun	bz	.Lagain1		# skip dataset header
187*4882a593Smuzhiyun	clc	0(3,%r4),.L_eof		# if it is EOFx
188*4882a593Smuzhiyun	bz	.Lagain1		# skip dateset trailer
189*4882a593Smuzhiyun	la	%r5,0(%r4,%r2)
190*4882a593Smuzhiyun	lr	%r3,%r2
191*4882a593Smuzhiyun	la	%r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
192*4882a593Smuzhiyun	mvc	0(256,%r3),0(%r4)
193*4882a593Smuzhiyun	mvc	256(256,%r3),256(%r4)
194*4882a593Smuzhiyun	mvc	512(256,%r3),512(%r4)
195*4882a593Smuzhiyun	mvc	768(122,%r3),768(%r4)
196*4882a593Smuzhiyun	slr	%r0,%r0
197*4882a593Smuzhiyun	b	.Lcntlp
198*4882a593Smuzhiyun.Ldelspc:
199*4882a593Smuzhiyun	ic	%r0,0(%r2,%r3)
200*4882a593Smuzhiyun	chi	%r0,0x20		# is it a space ?
201*4882a593Smuzhiyun	be	.Lcntlp
202*4882a593Smuzhiyun	ahi	%r2,1
203*4882a593Smuzhiyun	b	.Leolp
204*4882a593Smuzhiyun.Lcntlp:
205*4882a593Smuzhiyun	brct	%r2,.Ldelspc
206*4882a593Smuzhiyun.Leolp:
207*4882a593Smuzhiyun	slr	%r0,%r0
208*4882a593Smuzhiyun	stc	%r0,0(%r2,%r3)		# terminate buffer
209*4882a593Smuzhiyun.Lnopf:
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun#
212*4882a593Smuzhiyun# load ramdisk from ipl device
213*4882a593Smuzhiyun#
214*4882a593Smuzhiyun.Lagain2:
215*4882a593Smuzhiyun	l	%r2,.Linitrd		# addr of ramdisk
216*4882a593Smuzhiyun	st	%r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
217*4882a593Smuzhiyun	bas	%r14,.Lloader		# load ramdisk
218*4882a593Smuzhiyun	st	%r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd
219*4882a593Smuzhiyun	ltr	%r2,%r2
220*4882a593Smuzhiyun	bnz	.Lrdcont
221*4882a593Smuzhiyun	st	%r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
222*4882a593Smuzhiyun.Lrdcont:
223*4882a593Smuzhiyun	l	%r2,.Linitrd
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun	clc	0(3,%r2),.L_hdr		# skip HDRx and EOFx
226*4882a593Smuzhiyun	bz	.Lagain2
227*4882a593Smuzhiyun	clc	0(3,%r2),.L_eof
228*4882a593Smuzhiyun	bz	.Lagain2
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun#
231*4882a593Smuzhiyun# reset files in VM reader
232*4882a593Smuzhiyun#
233*4882a593Smuzhiyun	stidp	.Lcpuid			# store cpuid
234*4882a593Smuzhiyun	tm	.Lcpuid,0xff		# running VM ?
235*4882a593Smuzhiyun	bno	.Lnoreset
236*4882a593Smuzhiyun	la	%r2,.Lreset
237*4882a593Smuzhiyun	lhi	%r3,26
238*4882a593Smuzhiyun	diag	%r2,%r3,8
239*4882a593Smuzhiyun	la	%r5,.Lirb
240*4882a593Smuzhiyun	stsch	0(%r5)			# check if irq is pending
241*4882a593Smuzhiyun	tm	30(%r5),0x0f		# by verifying if any of the
242*4882a593Smuzhiyun	bnz	.Lwaitforirq		# activity or status control
243*4882a593Smuzhiyun	tm	31(%r5),0xff		# bits is set in the schib
244*4882a593Smuzhiyun	bz	.Lnoreset
245*4882a593Smuzhiyun.Lwaitforirq:
246*4882a593Smuzhiyun	bas	%r14,.Lirqwait		# wait for IO interrupt
247*4882a593Smuzhiyun	c	%r1,__LC_SUBCHANNEL_ID	# compare subchannel number
248*4882a593Smuzhiyun	bne	.Lwaitforirq
249*4882a593Smuzhiyun	la	%r5,.Lirb
250*4882a593Smuzhiyun	tsch	0(%r5)
251*4882a593Smuzhiyun.Lnoreset:
252*4882a593Smuzhiyun	b	.Lnoload
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun#
255*4882a593Smuzhiyun# everything loaded, go for it
256*4882a593Smuzhiyun#
257*4882a593Smuzhiyun.Lnoload:
258*4882a593Smuzhiyun	l	%r1,.Lstartup
259*4882a593Smuzhiyun	br	%r1
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun.Linitrd:.long _end			# default address of initrd
262*4882a593Smuzhiyun.Lparm:	.long  PARMAREA
263*4882a593Smuzhiyun.Lstartup: .long startup
264*4882a593Smuzhiyun.Lreset:.byte	0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
265*4882a593Smuzhiyun	.byte	0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
266*4882a593Smuzhiyun	.byte	0xc8,0xd6,0xd3,0xc4	# "change rdr all keep nohold"
267*4882a593Smuzhiyun.L_eof: .long	0xc5d6c600	 /* C'EOF' */
268*4882a593Smuzhiyun.L_hdr: .long	0xc8c4d900	 /* C'HDR' */
269*4882a593Smuzhiyun	.align	8
270*4882a593Smuzhiyun.Lcpuid:.fill	8,1,0
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun#
273*4882a593Smuzhiyun# startup-code at 0x10000, running in absolute addressing mode
274*4882a593Smuzhiyun# this is called either by the ipl loader or directly by PSW restart
275*4882a593Smuzhiyun# or linload or SALIPL
276*4882a593Smuzhiyun#
277*4882a593Smuzhiyun	.org	0x10000
278*4882a593SmuzhiyunENTRY(startup)
279*4882a593Smuzhiyun	j	.Lep_startup_normal
280*4882a593Smuzhiyun	.org	EP_OFFSET
281*4882a593Smuzhiyun#
282*4882a593Smuzhiyun# This is a list of s390 kernel entry points. At address 0x1000f the number of
283*4882a593Smuzhiyun# valid entry points is stored.
284*4882a593Smuzhiyun#
285*4882a593Smuzhiyun# IMPORTANT: Do not change this table, it is s390 kernel ABI!
286*4882a593Smuzhiyun#
287*4882a593Smuzhiyun	.ascii	EP_STRING
288*4882a593Smuzhiyun	.byte	0x00,0x01
289*4882a593Smuzhiyun#
290*4882a593Smuzhiyun# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode
291*4882a593Smuzhiyun#
292*4882a593Smuzhiyun	.org	0x10010
293*4882a593SmuzhiyunENTRY(startup_kdump)
294*4882a593Smuzhiyun	j	.Lep_startup_kdump
295*4882a593Smuzhiyun.Lep_startup_normal:
296*4882a593Smuzhiyun	mvi	__LC_AR_MODE_ID,1	# set esame flag
297*4882a593Smuzhiyun	slr	%r0,%r0 		# set cpuid to zero
298*4882a593Smuzhiyun	lhi	%r1,2			# mode 2 = esame (dump)
299*4882a593Smuzhiyun	sigp	%r1,%r0,0x12		# switch to esame mode
300*4882a593Smuzhiyun	bras	%r13,0f
301*4882a593Smuzhiyun	.fill	16,4,0x0
302*4882a593Smuzhiyun0:	lmh	%r0,%r15,0(%r13)	# clear high-order half of gprs
303*4882a593Smuzhiyun	sam64				# switch to 64 bit addressing mode
304*4882a593Smuzhiyun	basr	%r13,0			# get base
305*4882a593Smuzhiyun.LPG0:
306*4882a593Smuzhiyun	xc	0x200(256),0x200	# partially clear lowcore
307*4882a593Smuzhiyun	xc	0x300(256),0x300
308*4882a593Smuzhiyun	xc	0xe00(256),0xe00
309*4882a593Smuzhiyun	xc	0xf00(256),0xf00
310*4882a593Smuzhiyun	lctlg	%c0,%c15,.Lctl-.LPG0(%r13)	# load control registers
311*4882a593Smuzhiyun	stcke	__LC_BOOT_CLOCK
312*4882a593Smuzhiyun	mvc	__LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1
313*4882a593Smuzhiyun	spt	6f-.LPG0(%r13)
314*4882a593Smuzhiyun	mvc	__LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
315*4882a593Smuzhiyun	l	%r15,.Lstack-.LPG0(%r13)
316*4882a593Smuzhiyun	brasl	%r14,verify_facilities
317*4882a593Smuzhiyun	brasl	%r14,startup_kernel
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun.Lstack:
320*4882a593Smuzhiyun	.long	0x8000 + (1<<(PAGE_SHIFT+BOOT_STACK_ORDER)) - STACK_FRAME_OVERHEAD
321*4882a593Smuzhiyun	.align	8
322*4882a593Smuzhiyun6:	.long	0x7fffffff,0xffffffff
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun.Lctl:	.quad	0x04040000		# cr0: AFP registers & secondary space
325*4882a593Smuzhiyun	.quad	0			# cr1: primary space segment table
326*4882a593Smuzhiyun	.quad	.Lduct			# cr2: dispatchable unit control table
327*4882a593Smuzhiyun	.quad	0			# cr3: instruction authorization
328*4882a593Smuzhiyun	.quad	0xffff			# cr4: instruction authorization
329*4882a593Smuzhiyun	.quad	.Lduct			# cr5: primary-aste origin
330*4882a593Smuzhiyun	.quad	0			# cr6:	I/O interrupts
331*4882a593Smuzhiyun	.quad	0			# cr7:	secondary space segment table
332*4882a593Smuzhiyun	.quad	0x0000000000008000	# cr8:	access registers translation
333*4882a593Smuzhiyun	.quad	0			# cr9:	tracing off
334*4882a593Smuzhiyun	.quad	0			# cr10: tracing off
335*4882a593Smuzhiyun	.quad	0			# cr11: tracing off
336*4882a593Smuzhiyun	.quad	0			# cr12: tracing off
337*4882a593Smuzhiyun	.quad	0			# cr13: home space segment table
338*4882a593Smuzhiyun	.quad	0xc0000000		# cr14: machine check handling off
339*4882a593Smuzhiyun	.quad	.Llinkage_stack		# cr15: linkage stack operations
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun	.section .dma.data,"aw",@progbits
342*4882a593Smuzhiyun.Lduct: .long	0,.Laste,.Laste,0,.Lduald,0,0,0
343*4882a593Smuzhiyun	.long	0,0,0,0,0,0,0,0
344*4882a593Smuzhiyun.Llinkage_stack:
345*4882a593Smuzhiyun	.long	0,0,0x89000000,0,0,0,0x8a000000,0
346*4882a593Smuzhiyun	.align 64
347*4882a593Smuzhiyun.Laste:	.quad	0,0xffffffffffffffff,0,0,0,0,0,0
348*4882a593Smuzhiyun	.align	128
349*4882a593Smuzhiyun.Lduald:.rept	8
350*4882a593Smuzhiyun	.long	0x80000000,0,0,0	# invalid access-list entries
351*4882a593Smuzhiyun	.endr
352*4882a593Smuzhiyun	.previous
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun#include "head_kdump.S"
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun#
357*4882a593Smuzhiyun# This program check is active immediately after kernel start
358*4882a593Smuzhiyun# and until early_pgm_check_handler is set in kernel/early.c
359*4882a593Smuzhiyun# It simply saves general/control registers and psw in
360*4882a593Smuzhiyun# the save area and does disabled wait with a faulty address.
361*4882a593Smuzhiyun#
362*4882a593SmuzhiyunENTRY(startup_pgm_check_handler)
363*4882a593Smuzhiyun	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
364*4882a593Smuzhiyun	la	%r8,4095
365*4882a593Smuzhiyun	stctg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r8)
366*4882a593Smuzhiyun	stmg	%r0,%r7,__LC_GPREGS_SAVE_AREA-4095(%r8)
367*4882a593Smuzhiyun	mvc	__LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA_SYNC
368*4882a593Smuzhiyun	mvc	__LC_PSW_SAVE_AREA-4095(16,%r8),__LC_PGM_OLD_PSW
369*4882a593Smuzhiyun	mvc	__LC_RETURN_PSW(16),__LC_PGM_OLD_PSW
370*4882a593Smuzhiyun	ni	__LC_RETURN_PSW,0xfc	# remove IO and EX bits
371*4882a593Smuzhiyun	ni	__LC_RETURN_PSW+1,0xfb	# remove MCHK bit
372*4882a593Smuzhiyun	oi	__LC_RETURN_PSW+1,0x2	# set wait state bit
373*4882a593Smuzhiyun	larl	%r9,.Lold_psw_disabled_wait
374*4882a593Smuzhiyun	stg	%r9,__LC_PGM_NEW_PSW+8
375*4882a593Smuzhiyun	l	%r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r9)
376*4882a593Smuzhiyun	brasl	%r14,print_pgm_check_info
377*4882a593Smuzhiyun.Lold_psw_disabled_wait:
378*4882a593Smuzhiyun	la	%r8,4095
379*4882a593Smuzhiyun	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8)
380*4882a593Smuzhiyun	lpswe	__LC_RETURN_PSW		# disabled wait
381*4882a593Smuzhiyun.Ldump_info_stack:
382*4882a593Smuzhiyun	.long	0x5000 + PAGE_SIZE - STACK_FRAME_OVERHEAD
383*4882a593SmuzhiyunENDPROC(startup_pgm_check_handler)
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun#
386*4882a593Smuzhiyun# params at 10400 (setup.h)
387*4882a593Smuzhiyun# Must be keept in sync with struct parmarea in setup.h
388*4882a593Smuzhiyun#
389*4882a593Smuzhiyun	.org	PARMAREA
390*4882a593Smuzhiyun	.quad	0			# IPL_DEVICE
391*4882a593Smuzhiyun	.quad	0			# INITRD_START
392*4882a593Smuzhiyun	.quad	0			# INITRD_SIZE
393*4882a593Smuzhiyun	.quad	0			# OLDMEM_BASE
394*4882a593Smuzhiyun	.quad	0			# OLDMEM_SIZE
395*4882a593Smuzhiyun	.quad	kernel_version		# points to kernel version string
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun	.org	COMMAND_LINE
398*4882a593Smuzhiyun	.byte	"root=/dev/ram0 ro"
399*4882a593Smuzhiyun	.byte	0
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun	.org	EARLY_SCCB_OFFSET
402*4882a593Smuzhiyun	.fill	4096
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun	.org	HEAD_END
405