xref: /openbmc/linux/arch/s390/kernel/head64.S (revision a1e58bbd)
1/*
2 * arch/s390/kernel/head64.S
3 *
4 * Copyright (C) IBM Corp. 1999,2006
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
19startup:basr	%r13,0			# get base
20.LPG0:	l	%r13,0f-.LPG0(%r13)
21	b	0(%r13)
220:	.long	startup_continue
23
24#
25# params at 10400 (setup.h)
26#
27	.org	PARMAREA
28	.quad	0			# IPL_DEVICE
29	.quad	0			# INITRD_START
30	.quad	0			# INITRD_SIZE
31
32	.org	COMMAND_LINE
33	.byte	"root=/dev/ram0 ro"
34	.byte	0
35
36	.org	0x11000
37
38startup_continue:
39	basr	%r13,0			# get base
40.LPG1:	sll	%r13,1			# remove high order bit
41	srl	%r13,1
42
43#ifdef CONFIG_ZFCPDUMP
44
45	# check if we have been ipled using zfcp dump:
46
47	tm	0xb9,0x01		# test if subchannel is enabled
48	jno	.nodump			# subchannel disabled
49	l	%r1,0xb8
50	la	%r5,.Lipl_schib-.LPG1(%r13)
51	stsch	0(%r5)			# get schib of subchannel
52	jne	.nodump			# schib not available
53	tm	5(%r5),0x01		# devno valid?
54	jno	.nodump
55	tm	4(%r5),0x80		# qdio capable device?
56	jno	.nodump
57	l	%r2,20(%r0)		# address of ipl parameter block
58	lhi	%r3,0
59	ic	%r3,0x148(%r2)		# get opt field
60	chi	%r3,0x20		# load with dump?
61	jne	.nodump
62
63	# store all prefix registers in case of load with dump:
64
65	la	%r7,0			# base register for 0 page
66	la	%r8,0			# first cpu
67	l	%r11,.Lpref_arr_ptr-.LPG1(%r13)	# address of prefix array
68	ahi	%r11,4			# skip boot cpu
69	lr	%r12,%r11
70	ahi	%r12,(CONFIG_NR_CPUS*4)	# end of prefix array
71	stap	.Lcurrent_cpu+2-.LPG1(%r13)	# store current cpu addr
721:
73	cl	%r8,.Lcurrent_cpu-.LPG1(%r13)	# is ipl cpu ?
74	je	4f				# if yes get next cpu
752:
76	lr	%r9,%r7
77	sigp	%r9,%r8,0x9		# stop & store status of cpu
78	brc	8,3f			# accepted
79	brc	4,4f			# status stored: next cpu
80	brc	2,2b			# busy: 	 try again
81	brc	1,4f			# not op:	 next cpu
823:
83	mvc	0(4,%r11),264(%r7)	# copy prefix register to prefix array
84	ahi	%r11,4			# next element in prefix array
85	clr	%r11,%r12
86	je	5f			# no more space in prefix array
874:
88	ahi	%r8,1				# next cpu (r8 += 1)
89	cl	%r8,.Llast_cpu-.LPG1(%r13)	# is last possible cpu ?
90	jl	1b				# jump if not last cpu
915:
92	lhi	%r1,2			# mode 2 = esame (dump)
93	j	6f
94	.align 4
95.Lipl_schib:
96	.rept 13
97	.long 0
98	.endr
99.nodump:
100	lhi	%r1,1			# mode 1 = esame (normal ipl)
1016:
102#else
103	lhi	%r1,1			# mode 1 = esame (normal ipl)
104#endif /* CONFIG_ZFCPDUMP */
105	mvi	__LC_AR_MODE_ID,1	# set esame flag
106	slr	%r0,%r0 		# set cpuid to zero
107	sigp	%r1,%r0,0x12		# switch to esame mode
108	sam64				# switch to 64 bit mode
109	lctlg	%c0,%c15,.Lctl-.LPG1(%r13)	# load control registers
110	lg	%r12,.Lparmaddr-.LPG1(%r13)	# pointer to parameter area
111					# move IPL device to lowcore
112	mvc	__LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
113#
114# Setup stack
115#
116	larl	%r15,init_thread_union
117	lg	%r14,__TI_task(%r15)	# cache current in lowcore
118	stg	%r14,__LC_CURRENT
119	aghi	%r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
120	stg	%r15,__LC_KERNEL_STACK	# set end of kernel stack
121	aghi	%r15,-160
122	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
123#
124# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
125# and create a kernel NSS if the SAVESYS= parm is defined
126#
127	brasl	%r14,startup_init
128					# set program check new psw mask
129	mvc	__LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
130	larl	%r12,machine_flags
131#
132# find out if we have the MVPG instruction
133#
134	la	%r1,0f-.LPG1(%r13)	# set program check address
135	stg	%r1,__LC_PGM_NEW_PSW+8
136	sgr	%r0,%r0
137	lghi	%r1,0
138	lghi	%r2,0
139	mvpg	%r1,%r2 		# test MVPG instruction
140	oi	7(%r12),16		# set MVPG flag
1410:
142
143#
144# find out if the diag 0x44 works in 64 bit mode
145#
146	la	%r1,0f-.LPG1(%r13)	# set program check address
147	stg	%r1,__LC_PGM_NEW_PSW+8
148	diag	0,0,0x44		# test diag 0x44
149	oi	7(%r12),32		# set diag44 flag
1500:
151
152#
153# find out if we have the IDTE instruction
154#
155	la	%r1,0f-.LPG1(%r13)	# set program check address
156	stg	%r1,__LC_PGM_NEW_PSW+8
157	.long	0xb2b10000		# store facility list
158	tm	0xc8,0x08		# check bit for clearing-by-ASCE
159	bno	0f-.LPG1(%r13)
160	lhi	%r1,2048
161	lhi	%r2,0
162	.long	0xb98e2001
163	oi	7(%r12),0x80		# set IDTE flag
1640:
165
166#
167# find out if the diag 0x9c is available
168#
169	la	%r1,0f-.LPG1(%r13)	# set program check address
170	stg	%r1,__LC_PGM_NEW_PSW+8
171	stap	__LC_CPUID+4		# store cpu address
172	lh	%r1,__LC_CPUID+4
173	diag	%r1,0,0x9c		# test diag 0x9c
174	oi	6(%r12),1		# set diag9c flag
1750:
176
177#
178# find out if we have the MVCOS instruction
179#
180	la	%r1,0f-.LPG1(%r13)	# set program check address
181	stg	%r1,__LC_PGM_NEW_PSW+8
182	.short	0xc800			# mvcos 0(%r0),0(%r0),%r0
183	.short	0x0000
184	.short	0x0000
1850:	tm	0x8f,0x13		# special-operation exception?
186	bno	1f-.LPG1(%r13)		# if yes, MVCOS is present
187	oi	6(%r12),2		# set MVCOS flag
1881:
189
190	lpswe	.Lentry-.LPG1(13)	# jump to _stext in primary-space,
191					# virtual and never return ...
192	.align	16
193.Lentry:.quad	0x0000000180000000,_stext
194.Lctl:	.quad	0x04b50002		# cr0: various things
195	.quad	0			# cr1: primary space segment table
196	.quad	.Lduct			# cr2: dispatchable unit control table
197	.quad	0			# cr3: instruction authorization
198	.quad	0			# cr4: instruction authorization
199	.quad	.Lduct			# cr5: primary-aste origin
200	.quad	0			# cr6:	I/O interrupts
201	.quad	0			# cr7:	secondary space segment table
202	.quad	0			# cr8:	access registers translation
203	.quad	0			# cr9:	tracing off
204	.quad	0			# cr10: tracing off
205	.quad	0			# cr11: tracing off
206	.quad	0			# cr12: tracing off
207	.quad	0			# cr13: home space segment table
208	.quad	0xc0000000		# cr14: machine check handling off
209	.quad	0			# cr15: linkage stack operations
210.Lpcmsk:.quad	0x0000000180000000
211.L4malign:.quad 0xffffffffffc00000
212.Lscan2g:.quad	0x80000000 + 0x20000 - 8	# 2GB + 128K - 8
213.Lnop:	.long	0x07000700
214#ifdef CONFIG_ZFCPDUMP
215.Lcurrent_cpu:
216	.long 0x0
217.Llast_cpu:
218	.long 0x0000ffff
219.Lpref_arr_ptr:
220	.long zfcpdump_prefix_array
221#endif /* CONFIG_ZFCPDUMP */
222.Lparmaddr:
223	.quad	PARMAREA
224	.align	64
225.Lduct: .long	0,0,0,0,.Lduald,0,0,0
226	.long	0,0,0,0,0,0,0,0
227	.align	128
228.Lduald:.rept	8
229	.long	0x80000000,0,0,0	# invalid access-list entries
230	.endr
231
232	.org	0x12000
233	.globl	_ehead
234_ehead:
235#ifdef CONFIG_SHARED_KERNEL
236	.org	0x100000
237#endif
238
239#
240# startup-code, running in absolute addressing mode
241#
242	.globl	_stext
243_stext:	basr	%r13,0			# get base
244.LPG3:
245# check control registers
246	stctg	%c0,%c15,0(%r15)
247	oi	6(%r15),0x40		# enable sigp emergency signal
248	oi	4(%r15),0x10		# switch on low address proctection
249	lctlg	%c0,%c15,0(%r15)
250
251	lam	0,15,.Laregs-.LPG3(%r13)	# load acrs needed by uaccess
252	brasl	%r14,start_kernel	# go to C code
253#
254# We returned from start_kernel ?!? PANIK
255#
256	basr	%r13,0
257	lpswe	.Ldw-.(%r13)		# load disabled wait psw
258
259	.align	8
260.Ldw:	.quad	0x0002000180000000,0x0000000000000000
261.Laregs:.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
262