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