xref: /openbmc/linux/arch/s390/kernel/head64.S (revision 87c2ce3b)
1/*
2 * arch/s390/kernel/head64.S
3 *
4 * (C) Copyright IBM Corp. 1999,2005
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.LPG1:  sll   %r13,1                     # remove high order bit
21        srl   %r13,1
22	l     %r1,.Lget_ipl_device_addr-.LPG1(%r13)
23	basr  %r14,%r1
24        lhi   %r1,1                      # mode 1 = esame
25        slr   %r0,%r0                    # set cpuid to zero
26        sigp  %r1,%r0,0x12               # switch to esame mode
27	sam64				 # switch to 64 bit mode
28	lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
29	larl  %r12,_pstart               # pointer to parameter area
30					 # move IPL device to lowcore
31        mvc   __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
32
33#
34# clear bss memory
35#
36	larl  %r2,__bss_start           # start of bss segment
37        larl  %r3,_end                  # end of bss segment
38        sgr   %r3,%r2                   # length of bss
39        sgr   %r4,%r4                   #
40        sgr   %r5,%r5                   # set src,length and pad to zero
41        mvcle %r2,%r4,0                 # clear mem
42        jo    .-4                       # branch back, if not finish
43
44	l     %r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
45.Lservicecall:
46	stosm .Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts
47
48	stctg %r0,%r0,.Lcr-.LPG1(%r13)	# get cr0
49	la    %r1,0x200			# set bit 22
50	og    %r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
51	stg   %r1,.Lcr-.LPG1(%r13)
52	lctlg %r0,%r0,.Lcr-.LPG1(%r13)	# load modified cr0
53
54	mvc   __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
55	larl  %r1,.Lsclph
56	stg   %r1,__LC_EXT_NEW_PSW+8	# set handler
57
58	larl  %r4,_pstart		# %r4 is our index for sccb stuff
59	la    %r1,.Lsccb-PARMAREA(%r4)	# our sccb
60	.insn rre,0xb2200000,%r2,%r1	# service call
61	ipm   %r1
62	srl   %r1,28			# get cc code
63	xr    %r3,%r3
64	chi   %r1,3
65	be    .Lfchunk-.LPG1(%r13)	# leave
66	chi   %r1,2
67	be    .Lservicecall-.LPG1(%r13)
68	lpswe .Lwaitsclp-.LPG1(%r13)
69.Lsclph:
70	lh    %r1,.Lsccbr-PARMAREA(%r4)
71	chi   %r1,0x10			# 0x0010 is the sucess code
72	je    .Lprocsccb		# let's process the sccb
73	chi   %r1,0x1f0
74	bne   .Lfchunk-.LPG1(%r13)	# unhandled error code
75	c     %r2,.Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
76	bne   .Lfchunk-.LPG1(%r13)	# if no, give up
77	l     %r2,.Lrcp2-.LPG1(%r13)	# try with Read SCP
78	b     .Lservicecall-.LPG1(%r13)
79.Lprocsccb:
80	lghi  %r1,0
81	icm   %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
82	jnz   .Lscnd
83	lg    %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
84.Lscnd:
85	xr    %r3,%r3			# same logic
86	ic    %r3,.Lscpa1-PARMAREA(%r4)
87	chi   %r3,0x00
88	jne   .Lcompmem
89	l     %r3,.Lscpa2-PARMAREA(%r13)
90.Lcompmem:
91	mlgr  %r2,%r1			# mem in MB on 128-bit
92	l     %r1,.Lonemb-.LPG1(%r13)
93	mlgr  %r2,%r1			# mem size in bytes in %r3
94	b     .Lfchunk-.LPG1(%r13)
95
96	.align 4
97.Lget_ipl_device_addr:
98	.long .Lget_ipl_device
99.Lpmask:
100	.byte 0
101	.align 8
102.Lcr:
103	.quad 0x00  # place holder for cr0
104.Lwaitsclp:
105	.quad  0x0102000180000000,.Lsclph
106.Lrcp:
107	.int 0x00120001 # Read SCP forced code
108.Lrcp2:
109	.int 0x00020001 # Read SCP code
110.Lonemb:
111	.int 0x100000
112
113.Lfchunk:
114					 # set program check new psw mask
115	mvc   __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
116
117#
118# find memory chunks.
119#
120	lgr   %r9,%r3			 # end of mem
121	larl  %r1,.Lchkmem               # set program check address
122	stg   %r1,__LC_PGM_NEW_PSW+8
123	la    %r1,1                      # test in increments of 128KB
124	sllg  %r1,%r1,17
125	larl  %r3,memory_chunk
126	slgr  %r4,%r4                    # set start of chunk to zero
127	slgr  %r5,%r5                    # set end of chunk to zero
128	slr  %r6,%r6			 # set access code to zero
129	la    %r10,MEMORY_CHUNKS	 # number of chunks
130.Lloop:
131	tprot 0(%r5),0			 # test protection of first byte
132	ipm   %r7
133	srl   %r7,28
134	clr   %r6,%r7			 # compare cc with last access code
135	je    .Lsame
136	j     .Lchkmem
137.Lsame:
138	algr  %r5,%r1			 # add 128KB to end of chunk
139					 # no need to check here,
140	brc   12,.Lloop			 # this is the same chunk
141.Lchkmem:				 # > 16EB or tprot got a program check
142	clgr  %r4,%r5			 # chunk size > 0?
143	je    .Lchkloop
144	stg   %r4,0(%r3)		 # store start address of chunk
145	lgr   %r0,%r5
146	slgr  %r0,%r4
147	stg   %r0,8(%r3)		 # store size of chunk
148	st    %r6,20(%r3)		 # store type of chunk
149	la    %r3,24(%r3)
150	larl  %r8,memory_size
151	stg   %r5,0(%r8)                 # store memory size
152	ahi   %r10,-1			 # update chunk number
153.Lchkloop:
154	lr    %r6,%r7			 # set access code to last cc
155	# we got an exception or we're starting a new
156	# chunk , we must check if we should
157	# still try to find valid memory (if we detected
158	# the amount of available storage), and if we
159	# have chunks left
160	lghi  %r4,1
161	sllg  %r4,%r4,31
162	clgr  %r5,%r4
163	je    .Lhsaskip
164	xr    %r0, %r0
165	clgr  %r0, %r9			 # did we detect memory?
166	je    .Ldonemem			 # if not, leave
167	chi   %r10, 0			 # do we have chunks left?
168	je    .Ldonemem
169.Lhsaskip:
170	algr  %r5,%r1			 # add 128KB to end of chunk
171	lgr   %r4,%r5			 # potential new chunk
172	clgr  %r5,%r9			 # should we go on?
173	jl    .Lloop
174.Ldonemem:
175
176	larl  %r12,machine_flags
177#
178# find out if we are running under VM
179#
180        stidp  __LC_CPUID               # store cpuid
181	tm     __LC_CPUID,0xff          # running under VM ?
182	bno    0f-.LPG1(%r13)
183        oi     7(%r12),1                # set VM flag
1840:      lh     %r0,__LC_CPUID+4         # get cpu version
185        chi    %r0,0x7490               # running on a P/390 ?
186        bne    1f-.LPG1(%r13)
187        oi     7(%r12),4                # set P/390 flag
1881:
189
190#
191# find out if we have the MVPG instruction
192#
193	la     %r1,0f-.LPG1(%r13)       # set program check address
194	stg    %r1,__LC_PGM_NEW_PSW+8
195	sgr    %r0,%r0
196	lghi   %r1,0
197	lghi   %r2,0
198	mvpg   %r1,%r2                  # test MVPG instruction
199	oi     7(%r12),16               # set MVPG flag
2000:
201
202#
203# find out if the diag 0x44 works in 64 bit mode
204#
205	la     %r1,0f-.LPG1(%r13)	# set program check address
206	stg    %r1,__LC_PGM_NEW_PSW+8
207	diag   0,0,0x44			# test diag 0x44
208	oi     7(%r12),32		# set diag44 flag
2090:
210
211#
212# find out if we have the IDTE instruction
213#
214	la     %r1,0f-.LPG1(%r13)	# set program check address
215	stg    %r1,__LC_PGM_NEW_PSW+8
216	.long	0xb2b10000		# store facility list
217	tm	0xc8,0x08		# check bit for clearing-by-ASCE
218	bno	0f-.LPG1(%r13)
219	lhi	%r1,2094
220	lhi	%r2,0
221	.long	0xb98e2001
222	oi	7(%r12),0x80		# set IDTE flag
2230:
224
225        lpswe .Lentry-.LPG1(13)         # jump to _stext in primary-space,
226                                        # virtual and never return ...
227        .align 16
228.Lentry:.quad  0x0000000180000000,_stext
229.Lctl:  .quad  0x04b50002               # cr0: various things
230        .quad  0                        # cr1: primary space segment table
231        .quad  .Lduct                   # cr2: dispatchable unit control table
232        .quad  0                        # cr3: instruction authorization
233        .quad  0                        # cr4: instruction authorization
234        .quad  0xffffffffffffffff       # cr5: primary-aste origin
235        .quad  0                        # cr6:  I/O interrupts
236        .quad  0                        # cr7:  secondary space segment table
237        .quad  0                        # cr8:  access registers translation
238        .quad  0                        # cr9:  tracing off
239        .quad  0                        # cr10: tracing off
240        .quad  0                        # cr11: tracing off
241        .quad  0                        # cr12: tracing off
242        .quad  0                        # cr13: home space segment table
243        .quad  0xc0000000               # cr14: machine check handling off
244        .quad  0                        # cr15: linkage stack operations
245.Lpcmsk:.quad  0x0000000180000000
246.L4malign:.quad 0xffffffffffc00000
247.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
248.Lnop:	.long  0x07000700
249
250	.org PARMAREA-64
251.Lduct:	.long 0,0,0,0,0,0,0,0
252	.long 0,0,0,0,0,0,0,0
253
254#
255# params at 10400 (setup.h)
256#
257	.org   PARMAREA
258	.global _pstart
259_pstart:
260	.quad  0                        # IPL_DEVICE
261        .quad  RAMDISK_ORIGIN           # INITRD_START
262        .quad  RAMDISK_SIZE             # INITRD_SIZE
263
264        .org   COMMAND_LINE
265    	.byte  "root=/dev/ram0 ro"
266        .byte  0
267	.org   0x11000
268.Lsccb:
269	.hword 0x1000			# length, one page
270	.byte 0x00,0x00,0x00
271	.byte 0x80			# variable response bit set
272.Lsccbr:
273	.hword 0x00			# response code
274.Lscpincr1:
275	.hword 0x00
276.Lscpa1:
277	.byte 0x00
278	.fill 89,1,0
279.Lscpa2:
280	.int 0x00
281.Lscpincr2:
282	.quad 0x00
283	.fill 3984,1,0
284	.org 0x12000
285	.global _pend
286_pend:
287
288	GET_IPL_DEVICE
289
290#ifdef CONFIG_SHARED_KERNEL
291	.org   0x100000
292#endif
293
294#
295# startup-code, running in virtual mode
296#
297        .globl _stext
298_stext:	basr  %r13,0                    # get base
299.LPG3:
300#
301# Setup stack
302#
303	larl  %r15,init_thread_union
304	lg    %r14,__TI_task(%r15)      # cache current in lowcore
305	stg   %r14,__LC_CURRENT
306        aghi  %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
307        stg   %r15,__LC_KERNEL_STACK    # set end of kernel stack
308        aghi  %r15,-160
309        xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
310
311# check control registers
312        stctg  %c0,%c15,0(%r15)
313	oi     6(%r15),0x40             # enable sigp emergency signal
314	oi     4(%r15),0x10             # switch on low address proctection
315        lctlg  %c0,%c15,0(%r15)
316
317#
318        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
319        brasl  %r14,start_kernel        # go to C code
320#
321# We returned from start_kernel ?!? PANIK
322#
323        basr  %r13,0
324	lpswe .Ldw-.(%r13)           # load disabled wait psw
325#
326            .align 8
327.Ldw:       .quad  0x0002000180000000,0x0000000000000000
328.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
329
330