18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright IBM Corp. 1999, 2010
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *    Author(s): Hartmut Penner <hp@de.ibm.com>
68c2ecf20Sopenharmony_ci *		 Martin Schwidefsky <schwidefsky@de.ibm.com>
78c2ecf20Sopenharmony_ci *		 Rob van der Heij <rvdhei@iae.nl>
88c2ecf20Sopenharmony_ci *		 Heiko Carstens <heiko.carstens@de.ibm.com>
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * There are 5 different IPL methods
118c2ecf20Sopenharmony_ci *  1) load the image directly into ram at address 0 and do an PSW restart
128c2ecf20Sopenharmony_ci *  2) linload will load the image from address 0x10000 to memory 0x10000
138c2ecf20Sopenharmony_ci *     and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
148c2ecf20Sopenharmony_ci *  3) generate the tape ipl header, store the generated image on a tape
158c2ecf20Sopenharmony_ci *     and ipl from it
168c2ecf20Sopenharmony_ci *     In case of SL tape you need to IPL 5 times to get past VOL1 etc
178c2ecf20Sopenharmony_ci *  4) generate the vm reader ipl header, move the generated image to the
188c2ecf20Sopenharmony_ci *     VM reader (use option NOH!) and do a ipl from reader (VM only)
198c2ecf20Sopenharmony_ci *  5) direct call of start by the SALIPL loader
208c2ecf20Sopenharmony_ci *  We use the cpuid to distinguish between VM and native ipl
218c2ecf20Sopenharmony_ci *  params for kernel are pushed to 0x10400 (see setup.h)
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include <linux/init.h>
268c2ecf20Sopenharmony_ci#include <linux/linkage.h>
278c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
288c2ecf20Sopenharmony_ci#include <asm/thread_info.h>
298c2ecf20Sopenharmony_ci#include <asm/page.h>
308c2ecf20Sopenharmony_ci#include <asm/ptrace.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define ARCH_OFFSET	4
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci__HEAD
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define IPL_BS	0x730
378c2ecf20Sopenharmony_ci	.org	0
388c2ecf20Sopenharmony_ci	.long	0x00080000,0x80000000+iplstart	# The first 24 bytes are loaded
398c2ecf20Sopenharmony_ci	.long	0x02000018,0x60000050		# by ipl to addresses 0-23.
408c2ecf20Sopenharmony_ci	.long	0x02000068,0x60000050		# (a PSW and two CCWs).
418c2ecf20Sopenharmony_ci	.fill	80-24,1,0x40			# bytes 24-79 are discarded !!
428c2ecf20Sopenharmony_ci	.long	0x020000f0,0x60000050		# The next 160 byte are loaded
438c2ecf20Sopenharmony_ci	.long	0x02000140,0x60000050		# to addresses 0x18-0xb7
448c2ecf20Sopenharmony_ci	.long	0x02000190,0x60000050		# They form the continuation
458c2ecf20Sopenharmony_ci	.long	0x020001e0,0x60000050		# of the CCW program started
468c2ecf20Sopenharmony_ci	.long	0x02000230,0x60000050		# by ipl and load the range
478c2ecf20Sopenharmony_ci	.long	0x02000280,0x60000050		# 0x0f0-0x730 from the image
488c2ecf20Sopenharmony_ci	.long	0x020002d0,0x60000050		# to the range 0x0f0-0x730
498c2ecf20Sopenharmony_ci	.long	0x02000320,0x60000050		# in memory. At the end of
508c2ecf20Sopenharmony_ci	.long	0x02000370,0x60000050		# the channel program the PSW
518c2ecf20Sopenharmony_ci	.long	0x020003c0,0x60000050		# at location 0 is loaded.
528c2ecf20Sopenharmony_ci	.long	0x02000410,0x60000050		# Initial processing starts
538c2ecf20Sopenharmony_ci	.long	0x02000460,0x60000050		# at 0x200 = iplstart.
548c2ecf20Sopenharmony_ci	.long	0x020004b0,0x60000050
558c2ecf20Sopenharmony_ci	.long	0x02000500,0x60000050
568c2ecf20Sopenharmony_ci	.long	0x02000550,0x60000050
578c2ecf20Sopenharmony_ci	.long	0x020005a0,0x60000050
588c2ecf20Sopenharmony_ci	.long	0x020005f0,0x60000050
598c2ecf20Sopenharmony_ci	.long	0x02000640,0x60000050
608c2ecf20Sopenharmony_ci	.long	0x02000690,0x60000050
618c2ecf20Sopenharmony_ci	.long	0x020006e0,0x20000050
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	.org	__LC_RST_NEW_PSW		# 0x1a0
648c2ecf20Sopenharmony_ci	.quad	0,iplstart
658c2ecf20Sopenharmony_ci	.org	__LC_PGM_NEW_PSW		# 0x1d0
668c2ecf20Sopenharmony_ci	.quad	0x0000000180000000,startup_pgm_check_handler
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	.org	0x200
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#
718c2ecf20Sopenharmony_ci# subroutine to wait for end I/O
728c2ecf20Sopenharmony_ci#
738c2ecf20Sopenharmony_ci.Lirqwait:
748c2ecf20Sopenharmony_ci	mvc	__LC_IO_NEW_PSW(16),.Lnewpsw	# set up IO interrupt psw
758c2ecf20Sopenharmony_ci	lpsw	.Lwaitpsw
768c2ecf20Sopenharmony_ci.Lioint:
778c2ecf20Sopenharmony_ci	br	%r14
788c2ecf20Sopenharmony_ci	.align	8
798c2ecf20Sopenharmony_ci.Lnewpsw:
808c2ecf20Sopenharmony_ci	.quad	0x0000000080000000,.Lioint
818c2ecf20Sopenharmony_ci.Lwaitpsw:
828c2ecf20Sopenharmony_ci	.long	0x020a0000,0x80000000+.Lioint
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#
858c2ecf20Sopenharmony_ci# subroutine for loading cards from the reader
868c2ecf20Sopenharmony_ci#
878c2ecf20Sopenharmony_ci.Lloader:
888c2ecf20Sopenharmony_ci	la	%r4,0(%r14)
898c2ecf20Sopenharmony_ci	la	%r3,.Lorb		# r2 = address of orb into r2
908c2ecf20Sopenharmony_ci	la	%r5,.Lirb		# r4 = address of irb
918c2ecf20Sopenharmony_ci	la	%r6,.Lccws
928c2ecf20Sopenharmony_ci	la	%r7,20
938c2ecf20Sopenharmony_ci.Linit:
948c2ecf20Sopenharmony_ci	st	%r2,4(%r6)		# initialize CCW data addresses
958c2ecf20Sopenharmony_ci	la	%r2,0x50(%r2)
968c2ecf20Sopenharmony_ci	la	%r6,8(%r6)
978c2ecf20Sopenharmony_ci	bct	7,.Linit
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	lctl	%c6,%c6,.Lcr6		# set IO subclass mask
1008c2ecf20Sopenharmony_ci	slr	%r2,%r2
1018c2ecf20Sopenharmony_ci.Lldlp:
1028c2ecf20Sopenharmony_ci	ssch	0(%r3)			# load chunk of 1600 bytes
1038c2ecf20Sopenharmony_ci	bnz	.Llderr
1048c2ecf20Sopenharmony_ci.Lwait4irq:
1058c2ecf20Sopenharmony_ci	bas	%r14,.Lirqwait
1068c2ecf20Sopenharmony_ci	c	%r1,__LC_SUBCHANNEL_ID	# compare subchannel number
1078c2ecf20Sopenharmony_ci	bne	.Lwait4irq
1088c2ecf20Sopenharmony_ci	tsch	0(%r5)
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	slr	%r0,%r0
1118c2ecf20Sopenharmony_ci	ic	%r0,8(%r5)		# get device status
1128c2ecf20Sopenharmony_ci	chi	%r0,8			# channel end ?
1138c2ecf20Sopenharmony_ci	be	.Lcont
1148c2ecf20Sopenharmony_ci	chi	%r0,12			# channel end + device end ?
1158c2ecf20Sopenharmony_ci	be	.Lcont
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	l	%r0,4(%r5)
1188c2ecf20Sopenharmony_ci	s	%r0,8(%r3)		# r0/8 = number of ccws executed
1198c2ecf20Sopenharmony_ci	mhi	%r0,10			# *10 = number of bytes in ccws
1208c2ecf20Sopenharmony_ci	lh	%r3,10(%r5)		# get residual count
1218c2ecf20Sopenharmony_ci	sr	%r0,%r3 		# #ccws*80-residual=#bytes read
1228c2ecf20Sopenharmony_ci	ar	%r2,%r0
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	br	%r4			# r2 contains the total size
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci.Lcont:
1278c2ecf20Sopenharmony_ci	ahi	%r2,0x640		# add 0x640 to total size
1288c2ecf20Sopenharmony_ci	la	%r6,.Lccws
1298c2ecf20Sopenharmony_ci	la	%r7,20
1308c2ecf20Sopenharmony_ci.Lincr:
1318c2ecf20Sopenharmony_ci	l	%r0,4(%r6)		# update CCW data addresses
1328c2ecf20Sopenharmony_ci	ahi	%r0,0x640
1338c2ecf20Sopenharmony_ci	st	%r0,4(%r6)
1348c2ecf20Sopenharmony_ci	ahi	%r6,8
1358c2ecf20Sopenharmony_ci	bct	7,.Lincr
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	b	.Lldlp
1388c2ecf20Sopenharmony_ci.Llderr:
1398c2ecf20Sopenharmony_ci	lpsw	.Lcrash
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	.align	8
1428c2ecf20Sopenharmony_ci.Lorb:	.long	0x00000000,0x0080ff00,.Lccws
1438c2ecf20Sopenharmony_ci.Lirb:	.long	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1448c2ecf20Sopenharmony_ci.Lcr6:	.long	0xff000000
1458c2ecf20Sopenharmony_ci.Lloadp:.long	0,0
1468c2ecf20Sopenharmony_ci	.align	8
1478c2ecf20Sopenharmony_ci.Lcrash:.long	0x000a0000,0x00000000
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	.align	8
1508c2ecf20Sopenharmony_ci.Lccws: .rept	19
1518c2ecf20Sopenharmony_ci	.long	0x02600050,0x00000000
1528c2ecf20Sopenharmony_ci	.endr
1538c2ecf20Sopenharmony_ci	.long	0x02200050,0x00000000
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ciiplstart:
1568c2ecf20Sopenharmony_ci	mvi	__LC_AR_MODE_ID,1	# set esame flag
1578c2ecf20Sopenharmony_ci	slr	%r0,%r0			# set cpuid to zero
1588c2ecf20Sopenharmony_ci	lhi	%r1,2			# mode 2 = esame (dump)
1598c2ecf20Sopenharmony_ci	sigp	%r1,%r0,0x12		# switch to esame mode
1608c2ecf20Sopenharmony_ci	bras	%r13,0f
1618c2ecf20Sopenharmony_ci	.fill	16,4,0x0
1628c2ecf20Sopenharmony_ci0:	lmh	%r0,%r15,0(%r13)	# clear high-order half of gprs
1638c2ecf20Sopenharmony_ci	sam31				# switch to 31 bit addressing mode
1648c2ecf20Sopenharmony_ci	lh	%r1,__LC_SUBCHANNEL_ID	# test if subchannel number
1658c2ecf20Sopenharmony_ci	bct	%r1,.Lnoload		#  is valid
1668c2ecf20Sopenharmony_ci	l	%r1,__LC_SUBCHANNEL_ID	# load ipl subchannel number
1678c2ecf20Sopenharmony_ci	la	%r2,IPL_BS		# load start address
1688c2ecf20Sopenharmony_ci	bas	%r14,.Lloader		# load rest of ipl image
1698c2ecf20Sopenharmony_ci	l	%r12,.Lparm		# pointer to parameter area
1708c2ecf20Sopenharmony_ci	st	%r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci#
1738c2ecf20Sopenharmony_ci# load parameter file from ipl device
1748c2ecf20Sopenharmony_ci#
1758c2ecf20Sopenharmony_ci.Lagain1:
1768c2ecf20Sopenharmony_ci	l	%r2,.Linitrd		# ramdisk loc. is temp
1778c2ecf20Sopenharmony_ci	bas	%r14,.Lloader		# load parameter file
1788c2ecf20Sopenharmony_ci	ltr	%r2,%r2 		# got anything ?
1798c2ecf20Sopenharmony_ci	bz	.Lnopf
1808c2ecf20Sopenharmony_ci	chi	%r2,895
1818c2ecf20Sopenharmony_ci	bnh	.Lnotrunc
1828c2ecf20Sopenharmony_ci	la	%r2,895
1838c2ecf20Sopenharmony_ci.Lnotrunc:
1848c2ecf20Sopenharmony_ci	l	%r4,.Linitrd
1858c2ecf20Sopenharmony_ci	clc	0(3,%r4),.L_hdr		# if it is HDRx
1868c2ecf20Sopenharmony_ci	bz	.Lagain1		# skip dataset header
1878c2ecf20Sopenharmony_ci	clc	0(3,%r4),.L_eof		# if it is EOFx
1888c2ecf20Sopenharmony_ci	bz	.Lagain1		# skip dateset trailer
1898c2ecf20Sopenharmony_ci	la	%r5,0(%r4,%r2)
1908c2ecf20Sopenharmony_ci	lr	%r3,%r2
1918c2ecf20Sopenharmony_ci	la	%r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
1928c2ecf20Sopenharmony_ci	mvc	0(256,%r3),0(%r4)
1938c2ecf20Sopenharmony_ci	mvc	256(256,%r3),256(%r4)
1948c2ecf20Sopenharmony_ci	mvc	512(256,%r3),512(%r4)
1958c2ecf20Sopenharmony_ci	mvc	768(122,%r3),768(%r4)
1968c2ecf20Sopenharmony_ci	slr	%r0,%r0
1978c2ecf20Sopenharmony_ci	b	.Lcntlp
1988c2ecf20Sopenharmony_ci.Ldelspc:
1998c2ecf20Sopenharmony_ci	ic	%r0,0(%r2,%r3)
2008c2ecf20Sopenharmony_ci	chi	%r0,0x20		# is it a space ?
2018c2ecf20Sopenharmony_ci	be	.Lcntlp
2028c2ecf20Sopenharmony_ci	ahi	%r2,1
2038c2ecf20Sopenharmony_ci	b	.Leolp
2048c2ecf20Sopenharmony_ci.Lcntlp:
2058c2ecf20Sopenharmony_ci	brct	%r2,.Ldelspc
2068c2ecf20Sopenharmony_ci.Leolp:
2078c2ecf20Sopenharmony_ci	slr	%r0,%r0
2088c2ecf20Sopenharmony_ci	stc	%r0,0(%r2,%r3)		# terminate buffer
2098c2ecf20Sopenharmony_ci.Lnopf:
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci#
2128c2ecf20Sopenharmony_ci# load ramdisk from ipl device
2138c2ecf20Sopenharmony_ci#
2148c2ecf20Sopenharmony_ci.Lagain2:
2158c2ecf20Sopenharmony_ci	l	%r2,.Linitrd		# addr of ramdisk
2168c2ecf20Sopenharmony_ci	st	%r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
2178c2ecf20Sopenharmony_ci	bas	%r14,.Lloader		# load ramdisk
2188c2ecf20Sopenharmony_ci	st	%r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd
2198c2ecf20Sopenharmony_ci	ltr	%r2,%r2
2208c2ecf20Sopenharmony_ci	bnz	.Lrdcont
2218c2ecf20Sopenharmony_ci	st	%r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
2228c2ecf20Sopenharmony_ci.Lrdcont:
2238c2ecf20Sopenharmony_ci	l	%r2,.Linitrd
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	clc	0(3,%r2),.L_hdr		# skip HDRx and EOFx
2268c2ecf20Sopenharmony_ci	bz	.Lagain2
2278c2ecf20Sopenharmony_ci	clc	0(3,%r2),.L_eof
2288c2ecf20Sopenharmony_ci	bz	.Lagain2
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci#
2318c2ecf20Sopenharmony_ci# reset files in VM reader
2328c2ecf20Sopenharmony_ci#
2338c2ecf20Sopenharmony_ci	stidp	.Lcpuid			# store cpuid
2348c2ecf20Sopenharmony_ci	tm	.Lcpuid,0xff		# running VM ?
2358c2ecf20Sopenharmony_ci	bno	.Lnoreset
2368c2ecf20Sopenharmony_ci	la	%r2,.Lreset
2378c2ecf20Sopenharmony_ci	lhi	%r3,26
2388c2ecf20Sopenharmony_ci	diag	%r2,%r3,8
2398c2ecf20Sopenharmony_ci	la	%r5,.Lirb
2408c2ecf20Sopenharmony_ci	stsch	0(%r5)			# check if irq is pending
2418c2ecf20Sopenharmony_ci	tm	30(%r5),0x0f		# by verifying if any of the
2428c2ecf20Sopenharmony_ci	bnz	.Lwaitforirq		# activity or status control
2438c2ecf20Sopenharmony_ci	tm	31(%r5),0xff		# bits is set in the schib
2448c2ecf20Sopenharmony_ci	bz	.Lnoreset
2458c2ecf20Sopenharmony_ci.Lwaitforirq:
2468c2ecf20Sopenharmony_ci	bas	%r14,.Lirqwait		# wait for IO interrupt
2478c2ecf20Sopenharmony_ci	c	%r1,__LC_SUBCHANNEL_ID	# compare subchannel number
2488c2ecf20Sopenharmony_ci	bne	.Lwaitforirq
2498c2ecf20Sopenharmony_ci	la	%r5,.Lirb
2508c2ecf20Sopenharmony_ci	tsch	0(%r5)
2518c2ecf20Sopenharmony_ci.Lnoreset:
2528c2ecf20Sopenharmony_ci	b	.Lnoload
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci#
2558c2ecf20Sopenharmony_ci# everything loaded, go for it
2568c2ecf20Sopenharmony_ci#
2578c2ecf20Sopenharmony_ci.Lnoload:
2588c2ecf20Sopenharmony_ci	l	%r1,.Lstartup
2598c2ecf20Sopenharmony_ci	br	%r1
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci.Linitrd:.long _end			# default address of initrd
2628c2ecf20Sopenharmony_ci.Lparm:	.long  PARMAREA
2638c2ecf20Sopenharmony_ci.Lstartup: .long startup
2648c2ecf20Sopenharmony_ci.Lreset:.byte	0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
2658c2ecf20Sopenharmony_ci	.byte	0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
2668c2ecf20Sopenharmony_ci	.byte	0xc8,0xd6,0xd3,0xc4	# "change rdr all keep nohold"
2678c2ecf20Sopenharmony_ci.L_eof: .long	0xc5d6c600	 /* C'EOF' */
2688c2ecf20Sopenharmony_ci.L_hdr: .long	0xc8c4d900	 /* C'HDR' */
2698c2ecf20Sopenharmony_ci	.align	8
2708c2ecf20Sopenharmony_ci.Lcpuid:.fill	8,1,0
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci#
2738c2ecf20Sopenharmony_ci# startup-code at 0x10000, running in absolute addressing mode
2748c2ecf20Sopenharmony_ci# this is called either by the ipl loader or directly by PSW restart
2758c2ecf20Sopenharmony_ci# or linload or SALIPL
2768c2ecf20Sopenharmony_ci#
2778c2ecf20Sopenharmony_ci	.org	0x10000
2788c2ecf20Sopenharmony_ciENTRY(startup)
2798c2ecf20Sopenharmony_ci	j	.Lep_startup_normal
2808c2ecf20Sopenharmony_ci	.org	EP_OFFSET
2818c2ecf20Sopenharmony_ci#
2828c2ecf20Sopenharmony_ci# This is a list of s390 kernel entry points. At address 0x1000f the number of
2838c2ecf20Sopenharmony_ci# valid entry points is stored.
2848c2ecf20Sopenharmony_ci#
2858c2ecf20Sopenharmony_ci# IMPORTANT: Do not change this table, it is s390 kernel ABI!
2868c2ecf20Sopenharmony_ci#
2878c2ecf20Sopenharmony_ci	.ascii	EP_STRING
2888c2ecf20Sopenharmony_ci	.byte	0x00,0x01
2898c2ecf20Sopenharmony_ci#
2908c2ecf20Sopenharmony_ci# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode
2918c2ecf20Sopenharmony_ci#
2928c2ecf20Sopenharmony_ci	.org	0x10010
2938c2ecf20Sopenharmony_ciENTRY(startup_kdump)
2948c2ecf20Sopenharmony_ci	j	.Lep_startup_kdump
2958c2ecf20Sopenharmony_ci.Lep_startup_normal:
2968c2ecf20Sopenharmony_ci	mvi	__LC_AR_MODE_ID,1	# set esame flag
2978c2ecf20Sopenharmony_ci	slr	%r0,%r0 		# set cpuid to zero
2988c2ecf20Sopenharmony_ci	lhi	%r1,2			# mode 2 = esame (dump)
2998c2ecf20Sopenharmony_ci	sigp	%r1,%r0,0x12		# switch to esame mode
3008c2ecf20Sopenharmony_ci	bras	%r13,0f
3018c2ecf20Sopenharmony_ci	.fill	16,4,0x0
3028c2ecf20Sopenharmony_ci0:	lmh	%r0,%r15,0(%r13)	# clear high-order half of gprs
3038c2ecf20Sopenharmony_ci	sam64				# switch to 64 bit addressing mode
3048c2ecf20Sopenharmony_ci	basr	%r13,0			# get base
3058c2ecf20Sopenharmony_ci.LPG0:
3068c2ecf20Sopenharmony_ci	xc	0x200(256),0x200	# partially clear lowcore
3078c2ecf20Sopenharmony_ci	xc	0x300(256),0x300
3088c2ecf20Sopenharmony_ci	xc	0xe00(256),0xe00
3098c2ecf20Sopenharmony_ci	xc	0xf00(256),0xf00
3108c2ecf20Sopenharmony_ci	lctlg	%c0,%c15,.Lctl-.LPG0(%r13)	# load control registers
3118c2ecf20Sopenharmony_ci	stcke	__LC_BOOT_CLOCK
3128c2ecf20Sopenharmony_ci	mvc	__LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1
3138c2ecf20Sopenharmony_ci	spt	6f-.LPG0(%r13)
3148c2ecf20Sopenharmony_ci	mvc	__LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
3158c2ecf20Sopenharmony_ci	l	%r15,.Lstack-.LPG0(%r13)
3168c2ecf20Sopenharmony_ci	brasl	%r14,verify_facilities
3178c2ecf20Sopenharmony_ci	brasl	%r14,startup_kernel
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci.Lstack:
3208c2ecf20Sopenharmony_ci	.long	0x8000 + (1<<(PAGE_SHIFT+BOOT_STACK_ORDER)) - STACK_FRAME_OVERHEAD
3218c2ecf20Sopenharmony_ci	.align	8
3228c2ecf20Sopenharmony_ci6:	.long	0x7fffffff,0xffffffff
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci.Lctl:	.quad	0x04040000		# cr0: AFP registers & secondary space
3258c2ecf20Sopenharmony_ci	.quad	0			# cr1: primary space segment table
3268c2ecf20Sopenharmony_ci	.quad	.Lduct			# cr2: dispatchable unit control table
3278c2ecf20Sopenharmony_ci	.quad	0			# cr3: instruction authorization
3288c2ecf20Sopenharmony_ci	.quad	0xffff			# cr4: instruction authorization
3298c2ecf20Sopenharmony_ci	.quad	.Lduct			# cr5: primary-aste origin
3308c2ecf20Sopenharmony_ci	.quad	0			# cr6:	I/O interrupts
3318c2ecf20Sopenharmony_ci	.quad	0			# cr7:	secondary space segment table
3328c2ecf20Sopenharmony_ci	.quad	0x0000000000008000	# cr8:	access registers translation
3338c2ecf20Sopenharmony_ci	.quad	0			# cr9:	tracing off
3348c2ecf20Sopenharmony_ci	.quad	0			# cr10: tracing off
3358c2ecf20Sopenharmony_ci	.quad	0			# cr11: tracing off
3368c2ecf20Sopenharmony_ci	.quad	0			# cr12: tracing off
3378c2ecf20Sopenharmony_ci	.quad	0			# cr13: home space segment table
3388c2ecf20Sopenharmony_ci	.quad	0xc0000000		# cr14: machine check handling off
3398c2ecf20Sopenharmony_ci	.quad	.Llinkage_stack		# cr15: linkage stack operations
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	.section .dma.data,"aw",@progbits
3428c2ecf20Sopenharmony_ci.Lduct: .long	0,.Laste,.Laste,0,.Lduald,0,0,0
3438c2ecf20Sopenharmony_ci	.long	0,0,0,0,0,0,0,0
3448c2ecf20Sopenharmony_ci.Llinkage_stack:
3458c2ecf20Sopenharmony_ci	.long	0,0,0x89000000,0,0,0,0x8a000000,0
3468c2ecf20Sopenharmony_ci	.align 64
3478c2ecf20Sopenharmony_ci.Laste:	.quad	0,0xffffffffffffffff,0,0,0,0,0,0
3488c2ecf20Sopenharmony_ci	.align	128
3498c2ecf20Sopenharmony_ci.Lduald:.rept	8
3508c2ecf20Sopenharmony_ci	.long	0x80000000,0,0,0	# invalid access-list entries
3518c2ecf20Sopenharmony_ci	.endr
3528c2ecf20Sopenharmony_ci	.previous
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci#include "head_kdump.S"
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci#
3578c2ecf20Sopenharmony_ci# This program check is active immediately after kernel start
3588c2ecf20Sopenharmony_ci# and until early_pgm_check_handler is set in kernel/early.c
3598c2ecf20Sopenharmony_ci# It simply saves general/control registers and psw in
3608c2ecf20Sopenharmony_ci# the save area and does disabled wait with a faulty address.
3618c2ecf20Sopenharmony_ci#
3628c2ecf20Sopenharmony_ciENTRY(startup_pgm_check_handler)
3638c2ecf20Sopenharmony_ci	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
3648c2ecf20Sopenharmony_ci	la	%r8,4095
3658c2ecf20Sopenharmony_ci	stctg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r8)
3668c2ecf20Sopenharmony_ci	stmg	%r0,%r7,__LC_GPREGS_SAVE_AREA-4095(%r8)
3678c2ecf20Sopenharmony_ci	mvc	__LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA_SYNC
3688c2ecf20Sopenharmony_ci	mvc	__LC_PSW_SAVE_AREA-4095(16,%r8),__LC_PGM_OLD_PSW
3698c2ecf20Sopenharmony_ci	mvc	__LC_RETURN_PSW(16),__LC_PGM_OLD_PSW
3708c2ecf20Sopenharmony_ci	ni	__LC_RETURN_PSW,0xfc	# remove IO and EX bits
3718c2ecf20Sopenharmony_ci	ni	__LC_RETURN_PSW+1,0xfb	# remove MCHK bit
3728c2ecf20Sopenharmony_ci	oi	__LC_RETURN_PSW+1,0x2	# set wait state bit
3738c2ecf20Sopenharmony_ci	larl	%r9,.Lold_psw_disabled_wait
3748c2ecf20Sopenharmony_ci	stg	%r9,__LC_PGM_NEW_PSW+8
3758c2ecf20Sopenharmony_ci	l	%r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r9)
3768c2ecf20Sopenharmony_ci	brasl	%r14,print_pgm_check_info
3778c2ecf20Sopenharmony_ci.Lold_psw_disabled_wait:
3788c2ecf20Sopenharmony_ci	la	%r8,4095
3798c2ecf20Sopenharmony_ci	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8)
3808c2ecf20Sopenharmony_ci	lpswe	__LC_RETURN_PSW		# disabled wait
3818c2ecf20Sopenharmony_ci.Ldump_info_stack:
3828c2ecf20Sopenharmony_ci	.long	0x5000 + PAGE_SIZE - STACK_FRAME_OVERHEAD
3838c2ecf20Sopenharmony_ciENDPROC(startup_pgm_check_handler)
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci#
3868c2ecf20Sopenharmony_ci# params at 10400 (setup.h)
3878c2ecf20Sopenharmony_ci# Must be keept in sync with struct parmarea in setup.h
3888c2ecf20Sopenharmony_ci#
3898c2ecf20Sopenharmony_ci	.org	PARMAREA
3908c2ecf20Sopenharmony_ci	.quad	0			# IPL_DEVICE
3918c2ecf20Sopenharmony_ci	.quad	0			# INITRD_START
3928c2ecf20Sopenharmony_ci	.quad	0			# INITRD_SIZE
3938c2ecf20Sopenharmony_ci	.quad	0			# OLDMEM_BASE
3948c2ecf20Sopenharmony_ci	.quad	0			# OLDMEM_SIZE
3958c2ecf20Sopenharmony_ci	.quad	kernel_version		# points to kernel version string
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	.org	COMMAND_LINE
3988c2ecf20Sopenharmony_ci	.byte	"root=/dev/ram0 ro"
3998c2ecf20Sopenharmony_ci	.byte	0
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	.org	EARLY_SCCB_OFFSET
4028c2ecf20Sopenharmony_ci	.fill	4096
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	.org	HEAD_END
405