head64.S 10.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 * arch/s390/kernel/head64.S
Linus Torvalds's avatar
Linus Torvalds committed
3
 *
Heiko Carstens's avatar
Heiko Carstens committed
4
 * Copyright (C) IBM Corp. 1999,2006
5 6 7 8 9
 *
 *   Author(s):	Hartmut Penner <hp@de.ibm.com>
 *		Martin Schwidefsky <schwidefsky@de.ibm.com>
 *		Rob van der Heij <rvdhei@iae.nl>
 *		Heiko Carstens <heiko.carstens@de.ibm.com>
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13
 *
 */

#
14
# startup-code at 0x10000, running in absolute addressing mode
Linus Torvalds's avatar
Linus Torvalds committed
15 16 17
# this is called either by the ipl loader or directly by PSW restart
# or linload or SALIPL
#
Heiko Carstens's avatar
Heiko Carstens committed
18 19 20 21 22 23 24 25 26 27 28
	.org  0x10000
startup:basr  %r13,0			 # get base
.LPG0:	l     %r13,0f-.LPG0(%r13)
	b     0(%r13)
0:	.long startup_continue

#
# params at 10400 (setup.h)
#
	.org   PARMAREA
	.quad  0			# IPL_DEVICE
29 30
	.quad  0			# INITRD_START
	.quad  0			# INITRD_SIZE
Heiko Carstens's avatar
Heiko Carstens committed
31 32 33 34 35 36 37 38 39

	.org   COMMAND_LINE
	.byte  "root=/dev/ram0 ro"
	.byte  0

	.org   0x11000

startup_continue:
	basr  %r13,0			 # get base
Linus Torvalds's avatar
Linus Torvalds committed
40 41 42
.LPG1:  sll   %r13,1                     # remove high order bit
        srl   %r13,1
        lhi   %r1,1                      # mode 1 = esame
Michael Holzheu's avatar
Michael Holzheu committed
43
	mvi   __LC_AR_MODE_ID,1		 # set esame flag
Linus Torvalds's avatar
Linus Torvalds committed
44 45 46 47
        slr   %r0,%r0                    # set cpuid to zero
        sigp  %r1,%r0,0x12               # switch to esame mode
	sam64				 # switch to 64 bit mode
	lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
Heiko Carstens's avatar
Heiko Carstens committed
48
	lg    %r12,.Lparmaddr-.LPG1(%r13)# pointer to parameter area
Linus Torvalds's avatar
Linus Torvalds committed
49 50
					 # move IPL device to lowcore
        mvc   __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
51 52 53 54 55 56 57 58 59 60
#
# Setup stack
#
	larl  %r15,init_thread_union
	lg    %r14,__TI_task(%r15)	# cache current in lowcore
	stg   %r14,__LC_CURRENT
	aghi  %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
	stg   %r15,__LC_KERNEL_STACK	# set end of kernel stack
	aghi  %r15,-160
	xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
Linus Torvalds's avatar
Linus Torvalds committed
61

62
	brasl %r14,ipl_save_parameters
Linus Torvalds's avatar
Linus Torvalds committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
#
# clear bss memory
#
	larl  %r2,__bss_start           # start of bss segment
        larl  %r3,_end                  # end of bss segment
        sgr   %r3,%r2                   # length of bss
        sgr   %r4,%r4                   #
        sgr   %r5,%r5                   # set src,length and pad to zero
        mvcle %r2,%r4,0                 # clear mem
        jo    .-4                       # branch back, if not finish

	l     %r2,.Lrcp-.LPG1(%r13)	# Read SCP forced command word
.Lservicecall:
	stosm .Lpmask-.LPG1(%r13),0x01	# authorize ext interrupts

	stctg %r0,%r0,.Lcr-.LPG1(%r13)	# get cr0
	la    %r1,0x200			# set bit 22
	og    %r1,.Lcr-.LPG1(%r13)	# or old cr0 with r1
	stg   %r1,.Lcr-.LPG1(%r13)
	lctlg %r0,%r0,.Lcr-.LPG1(%r13)	# load modified cr0

	mvc   __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
	larl  %r1,.Lsclph
	stg   %r1,__LC_EXT_NEW_PSW+8	# set handler

Heiko Carstens's avatar
Heiko Carstens committed
88 89
	larl  %r4,.Lsccb		# %r4 is our index for sccb stuff
	lgr   %r1,%r4			# our sccb
Linus Torvalds's avatar
Linus Torvalds committed
90 91 92 93 94 95 96 97
	.insn rre,0xb2200000,%r2,%r1	# service call
	ipm   %r1
	srl   %r1,28			# get cc code
	xr    %r3,%r3
	chi   %r1,3
	be    .Lfchunk-.LPG1(%r13)	# leave
	chi   %r1,2
	be    .Lservicecall-.LPG1(%r13)
98
	lpswe .Lwaitsclp-.LPG1(%r13)
Linus Torvalds's avatar
Linus Torvalds committed
99
.Lsclph:
Heiko Carstens's avatar
Heiko Carstens committed
100
	lh    %r1,.Lsccbr-.Lsccb(%r4)
Linus Torvalds's avatar
Linus Torvalds committed
101 102 103 104 105 106 107 108 109
	chi   %r1,0x10			# 0x0010 is the sucess code
	je    .Lprocsccb		# let's process the sccb
	chi   %r1,0x1f0
	bne   .Lfchunk-.LPG1(%r13)	# unhandled error code
	c     %r2,.Lrcp-.LPG1(%r13)	# Did we try Read SCP forced
	bne   .Lfchunk-.LPG1(%r13)	# if no, give up
	l     %r2,.Lrcp2-.LPG1(%r13)	# try with Read SCP
	b     .Lservicecall-.LPG1(%r13)
.Lprocsccb:
110
	lghi  %r1,0
Heiko Carstens's avatar
Heiko Carstens committed
111
	icm   %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
112
	jnz   .Lscnd
Heiko Carstens's avatar
Heiko Carstens committed
113
	lg    %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one
Linus Torvalds's avatar
Linus Torvalds committed
114 115
.Lscnd:
	xr    %r3,%r3			# same logic
Heiko Carstens's avatar
Heiko Carstens committed
116
	ic    %r3,.Lscpa1-.Lsccb(%r4)
Linus Torvalds's avatar
Linus Torvalds committed
117 118
	chi   %r3,0x00
	jne   .Lcompmem
Heiko Carstens's avatar
Heiko Carstens committed
119
	l     %r3,.Lscpa2-.Lsccb(%r4)
Linus Torvalds's avatar
Linus Torvalds committed
120 121 122 123 124 125
.Lcompmem:
	mlgr  %r2,%r1			# mem in MB on 128-bit
	l     %r1,.Lonemb-.LPG1(%r13)
	mlgr  %r2,%r1			# mem size in bytes in %r3
	b     .Lfchunk-.LPG1(%r13)

126
	.align 4
Linus Torvalds's avatar
Linus Torvalds committed
127 128 129 130 131 132
.Lpmask:
	.byte 0
	.align 8
.Lcr:
	.quad 0x00  # place holder for cr0
.Lwaitsclp:
133
	.quad  0x0102000180000000,.Lsclph
Linus Torvalds's avatar
Linus Torvalds committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
.Lrcp:
	.int 0x00120001 # Read SCP forced code
.Lrcp2:
	.int 0x00020001 # Read SCP code
.Lonemb:
	.int 0x100000

.Lfchunk:
					 # set program check new psw mask
	mvc   __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)

#
# find memory chunks.
#
	lgr   %r9,%r3			 # end of mem
	larl  %r1,.Lchkmem               # set program check address
	stg   %r1,__LC_PGM_NEW_PSW+8
	la    %r1,1                      # test in increments of 128KB
	sllg  %r1,%r1,17
	larl  %r3,memory_chunk
	slgr  %r4,%r4                    # set start of chunk to zero
	slgr  %r5,%r5                    # set end of chunk to zero
	slr  %r6,%r6			 # set access code to zero
	la    %r10,MEMORY_CHUNKS	 # number of chunks
.Lloop:
	tprot 0(%r5),0			 # test protection of first byte
	ipm   %r7
	srl   %r7,28
	clr   %r6,%r7			 # compare cc with last access code
	je    .Lsame
	j     .Lchkmem
.Lsame:
	algr  %r5,%r1			 # add 128KB to end of chunk
					 # no need to check here,
	brc   12,.Lloop			 # this is the same chunk
.Lchkmem:				 # > 16EB or tprot got a program check
	clgr  %r4,%r5			 # chunk size > 0?
	je    .Lchkloop
	stg   %r4,0(%r3)		 # store start address of chunk
	lgr   %r0,%r5
	slgr  %r0,%r4
	stg   %r0,8(%r3)		 # store size of chunk
	st    %r6,20(%r3)		 # store type of chunk
	la    %r3,24(%r3)
	larl  %r8,memory_size
	stg   %r5,0(%r8)                 # store memory size
	ahi   %r10,-1			 # update chunk number
.Lchkloop:
	lr    %r6,%r7			 # set access code to last cc
	# we got an exception or we're starting a new
	# chunk , we must check if we should
	# still try to find valid memory (if we detected
	# the amount of available storage), and if we
	# have chunks left
	lghi  %r4,1
	sllg  %r4,%r4,31
	clgr  %r5,%r4
	je    .Lhsaskip
	xr    %r0, %r0
	clgr  %r0, %r9			 # did we detect memory?
	je    .Ldonemem			 # if not, leave
	chi   %r10, 0			 # do we have chunks left?
	je    .Ldonemem
.Lhsaskip:
	algr  %r5,%r1			 # add 128KB to end of chunk
	lgr   %r4,%r5			 # potential new chunk
	clgr  %r5,%r9			 # should we go on?
	jl    .Lloop
.Ldonemem:		

	larl  %r12,machine_flags
#
# find out if we are running under VM
#
        stidp  __LC_CPUID               # store cpuid
	tm     __LC_CPUID,0xff          # running under VM ?
	bno    0f-.LPG1(%r13)
        oi     7(%r12),1                # set VM flag
0:      lh     %r0,__LC_CPUID+4         # get cpu version
        chi    %r0,0x7490               # running on a P/390 ?
        bne    1f-.LPG1(%r13)
        oi     7(%r12),4                # set P/390 flag
1:

#
# find out if we have the MVPG instruction
#
	la     %r1,0f-.LPG1(%r13)       # set program check address
	stg    %r1,__LC_PGM_NEW_PSW+8
	sgr    %r0,%r0
	lghi   %r1,0
	lghi   %r2,0
	mvpg   %r1,%r2                  # test MVPG instruction
	oi     7(%r12),16               # set MVPG flag
0:

#
# find out if the diag 0x44 works in 64 bit mode
#
	la     %r1,0f-.LPG1(%r13)	# set program check address
	stg    %r1,__LC_PGM_NEW_PSW+8
	diag   0,0,0x44			# test diag 0x44
	oi     7(%r12),32		# set diag44 flag
0:	

#
# find out if we have the IDTE instruction
#
	la     %r1,0f-.LPG1(%r13)	# set program check address
	stg    %r1,__LC_PGM_NEW_PSW+8
	.long	0xb2b10000		# store facility list
	tm	0xc8,0x08		# check bit for clearing-by-ASCE
	bno	0f-.LPG1(%r13)
	lhi	%r1,2094
	lhi	%r2,0
	.long	0xb98e2001
	oi	7(%r12),0x80		# set IDTE flag
0:

253 254 255 256 257 258 259 260 261 262 263 264 265
#
# find out if we have the MVCOS instruction
#
	la	%r1,0f-.LPG1(%r13)	# set program check address
	stg	%r1,__LC_PGM_NEW_PSW+8
	.short	0xc800			# mvcos 0(%r0),0(%r0),%r0
	.short	0x0000
	.short	0x0000
0:	tm	0x8f,0x13		# special-operation exception?
	bno	1f-.LPG1(%r13)		# if yes, MVCOS is present
	oi	6(%r12),2		# set MVCOS flag
1:

Linus Torvalds's avatar
Linus Torvalds committed
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
        lpswe .Lentry-.LPG1(13)         # jump to _stext in primary-space,
                                        # virtual and never return ...
        .align 16
.Lentry:.quad  0x0000000180000000,_stext
.Lctl:  .quad  0x04b50002               # cr0: various things
        .quad  0                        # cr1: primary space segment table
        .quad  .Lduct                   # cr2: dispatchable unit control table
        .quad  0                        # cr3: instruction authorization
        .quad  0                        # cr4: instruction authorization
        .quad  0xffffffffffffffff       # cr5: primary-aste origin
        .quad  0                        # cr6:  I/O interrupts
        .quad  0                        # cr7:  secondary space segment table
        .quad  0                        # cr8:  access registers translation
        .quad  0                        # cr9:  tracing off
        .quad  0                        # cr10: tracing off
        .quad  0                        # cr11: tracing off
        .quad  0                        # cr12: tracing off
        .quad  0                        # cr13: home space segment table
        .quad  0xc0000000               # cr14: machine check handling off
        .quad  0                        # cr15: linkage stack operations
Heiko Carstens's avatar
Heiko Carstens committed
286 287
.Lduct: .long 0,0,0,0,0,0,0,0
	.long 0,0,0,0,0,0,0,0
Linus Torvalds's avatar
Linus Torvalds committed
288 289 290 291
.Lpcmsk:.quad  0x0000000180000000
.L4malign:.quad 0xffffffffffc00000
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
.Lnop:	.long  0x07000700
Heiko Carstens's avatar
Heiko Carstens committed
292 293
.Lparmaddr:
	.quad	PARMAREA
Linus Torvalds's avatar
Linus Torvalds committed
294

295 296 297 298 299 300 301 302 303 304 305 306 307
	.globl ipl_schib
ipl_schib:
	.rept 13
	.long 0
	.endr

	.globl ipl_flags
ipl_flags:
	.long 0
	.globl ipl_devno
ipl_devno:
	.word 0

308
	.org	0x12000
Michael Holzheu's avatar
Michael Holzheu committed
309 310
.globl s390_readinfo_sccb
s390_readinfo_sccb:
Linus Torvalds's avatar
Linus Torvalds committed
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
.Lsccb:
	.hword 0x1000			# length, one page
	.byte 0x00,0x00,0x00
	.byte 0x80			# variable response bit set
.Lsccbr:
	.hword 0x00			# response code
.Lscpincr1:
	.hword 0x00
.Lscpa1:
	.byte 0x00
	.fill 89,1,0
.Lscpa2:
	.int 0x00
.Lscpincr2:
	.quad 0x00
	.fill 3984,1,0
327
	.org	0x13000
328

Linus Torvalds's avatar
Linus Torvalds committed
329 330 331 332 333
#ifdef CONFIG_SHARED_KERNEL
	.org   0x100000
#endif
	
#
Heiko Carstens's avatar
Heiko Carstens committed
334
# startup-code, running in absolute addressing mode
Linus Torvalds's avatar
Linus Torvalds committed
335 336 337
#
        .globl _stext
_stext:	basr  %r13,0                    # get base
338
.LPG3:
Linus Torvalds's avatar
Linus Torvalds committed
339 340
# check control registers
        stctg  %c0,%c15,0(%r15)
341
	oi     6(%r15),0x40             # enable sigp emergency signal
Linus Torvalds's avatar
Linus Torvalds committed
342 343 344
	oi     4(%r15),0x10             # switch on low address proctection
        lctlg  %c0,%c15,0(%r15)

345
        lam    0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
Linus Torvalds's avatar
Linus Torvalds committed
346 347 348 349 350 351
        brasl  %r14,start_kernel        # go to C code
#
# We returned from start_kernel ?!? PANIK
#
        basr  %r13,0
	lpswe .Ldw-.(%r13)           # load disabled wait psw
352

Linus Torvalds's avatar
Linus Torvalds committed
353 354 355
            .align 8
.Ldw:       .quad  0x0002000180000000,0x0000000000000000
.Laregs:    .long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0