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