xref: /openbmc/linux/arch/s390/kernel/entry.S (revision 10bc15ba3a853723267016274b58be6c9a6e64da)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
24bfc86ceSHeiko Carstens/*
34bfc86ceSHeiko Carstens *    S390 low-level entry points.
44bfc86ceSHeiko Carstens *
54bfc86ceSHeiko Carstens *    Copyright IBM Corp. 1999, 2012
64bfc86ceSHeiko Carstens *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
74bfc86ceSHeiko Carstens *		 Hartmut Penner (hp@de.ibm.com),
84bfc86ceSHeiko Carstens *		 Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
94bfc86ceSHeiko Carstens */
104bfc86ceSHeiko Carstens
114bfc86ceSHeiko Carstens#include <linux/init.h>
124bfc86ceSHeiko Carstens#include <linux/linkage.h>
13d09a307fSHeiko Carstens#include <asm/asm-extable.h>
14b058661aSMartin Schwidefsky#include <asm/alternative-asm.h>
154bfc86ceSHeiko Carstens#include <asm/processor.h>
164bfc86ceSHeiko Carstens#include <asm/cache.h>
17dc24b7b4SHendrik Brueckner#include <asm/dwarf.h>
184bfc86ceSHeiko Carstens#include <asm/errno.h>
194bfc86ceSHeiko Carstens#include <asm/ptrace.h>
204bfc86ceSHeiko Carstens#include <asm/thread_info.h>
214bfc86ceSHeiko Carstens#include <asm/asm-offsets.h>
224bfc86ceSHeiko Carstens#include <asm/unistd.h>
234bfc86ceSHeiko Carstens#include <asm/page.h>
244bfc86ceSHeiko Carstens#include <asm/sigp.h>
254bfc86ceSHeiko Carstens#include <asm/irq.h>
269977e886SHendrik Brueckner#include <asm/vx-insn.h>
2783abeffbSHendrik Brueckner#include <asm/setup.h>
2883abeffbSHendrik Brueckner#include <asm/nmi.h>
29711f5df7SAl Viro#include <asm/export.h>
306dd85fbbSMartin Schwidefsky#include <asm/nospec-insn.h>
314bfc86ceSHeiko Carstens
324bfc86ceSHeiko Carstens__PT_R0      =	__PT_GPRS
334bfc86ceSHeiko Carstens__PT_R1      =	__PT_GPRS + 8
344bfc86ceSHeiko Carstens__PT_R2      =	__PT_GPRS + 16
354bfc86ceSHeiko Carstens__PT_R3      =	__PT_GPRS + 24
364bfc86ceSHeiko Carstens__PT_R4      =	__PT_GPRS + 32
374bfc86ceSHeiko Carstens__PT_R5      =	__PT_GPRS + 40
384bfc86ceSHeiko Carstens__PT_R6      =	__PT_GPRS + 48
394bfc86ceSHeiko Carstens__PT_R7      =	__PT_GPRS + 56
404bfc86ceSHeiko Carstens__PT_R8      =	__PT_GPRS + 64
414bfc86ceSHeiko Carstens__PT_R9      =	__PT_GPRS + 72
424bfc86ceSHeiko Carstens__PT_R10     =	__PT_GPRS + 80
434bfc86ceSHeiko Carstens__PT_R11     =	__PT_GPRS + 88
444bfc86ceSHeiko Carstens__PT_R12     =	__PT_GPRS + 96
454bfc86ceSHeiko Carstens__PT_R13     =	__PT_GPRS + 104
464bfc86ceSHeiko Carstens__PT_R14     =	__PT_GPRS + 112
474bfc86ceSHeiko Carstens__PT_R15     =	__PT_GPRS + 120
484bfc86ceSHeiko Carstens
493a890380SHeiko CarstensSTACK_SHIFT = PAGE_SHIFT + THREAD_SIZE_ORDER
504bfc86ceSHeiko CarstensSTACK_SIZE  = 1 << STACK_SHIFT
514bfc86ceSHeiko CarstensSTACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
524bfc86ceSHeiko Carstens
53e5b98199SMartin Schwidefsky_LPP_OFFSET	= __LC_LPP
54e5b98199SMartin Schwidefsky
553b051e89SSven Schnelle	.macro STBEAR address
563b051e89SSven Schnelle	ALTERNATIVE "", ".insn	s,0xb2010000,\address", 193
573b051e89SSven Schnelle	.endm
583b051e89SSven Schnelle
593b051e89SSven Schnelle	.macro LBEAR address
603b051e89SSven Schnelle	ALTERNATIVE "", ".insn	s,0xb2000000,\address", 193
613b051e89SSven Schnelle	.endm
623b051e89SSven Schnelle
633b051e89SSven Schnelle	.macro LPSWEY address,lpswe
643b051e89SSven Schnelle	ALTERNATIVE "b \lpswe", ".insn siy,0xeb0000000071,\address,0", 193
653b051e89SSven Schnelle	.endm
663b051e89SSven Schnelle
673b051e89SSven Schnelle	.macro MBEAR reg
683b051e89SSven Schnelle	ALTERNATIVE "", __stringify(mvc __PT_LAST_BREAK(8,\reg),__LC_LAST_BREAK), 193
693b051e89SSven Schnelle	.endm
703b051e89SSven Schnelle
71ce3dc447SMartin Schwidefsky	.macro	CHECK_STACK savearea
724bfc86ceSHeiko Carstens#ifdef CONFIG_CHECK_STACK
73ce3dc447SMartin Schwidefsky	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
744bfc86ceSHeiko Carstens	lghi	%r14,\savearea
754bfc86ceSHeiko Carstens	jz	stack_overflow
764bfc86ceSHeiko Carstens#endif
774bfc86ceSHeiko Carstens	.endm
784bfc86ceSHeiko Carstens
79ce3dc447SMartin Schwidefsky	.macro	CHECK_VMAP_STACK savearea,oklabel
80ce3dc447SMartin Schwidefsky#ifdef CONFIG_VMAP_STACK
81ce3dc447SMartin Schwidefsky	lgr	%r14,%r15
82ce3dc447SMartin Schwidefsky	nill	%r14,0x10000 - STACK_SIZE
83ce3dc447SMartin Schwidefsky	oill	%r14,STACK_INIT
84ce3dc447SMartin Schwidefsky	clg	%r14,__LC_KERNEL_STACK
85ce3dc447SMartin Schwidefsky	je	\oklabel
86ce3dc447SMartin Schwidefsky	clg	%r14,__LC_ASYNC_STACK
87ce3dc447SMartin Schwidefsky	je	\oklabel
88b61b1595SSven Schnelle	clg	%r14,__LC_MCCK_STACK
89b61b1595SSven Schnelle	je	\oklabel
90ce3dc447SMartin Schwidefsky	clg	%r14,__LC_NODAT_STACK
91ce3dc447SMartin Schwidefsky	je	\oklabel
92ce3dc447SMartin Schwidefsky	clg	%r14,__LC_RESTART_STACK
93ce3dc447SMartin Schwidefsky	je	\oklabel
94ce3dc447SMartin Schwidefsky	lghi	%r14,\savearea
95ce3dc447SMartin Schwidefsky	j	stack_overflow
96ce3dc447SMartin Schwidefsky#else
97ce3dc447SMartin Schwidefsky	j	\oklabel
98ce3dc447SMartin Schwidefsky#endif
99ce3dc447SMartin Schwidefsky	.endm
100ce3dc447SMartin Schwidefsky
10183abeffbSHendrik Brueckner	/*
10283abeffbSHendrik Brueckner	 * The TSTMSK macro generates a test-under-mask instruction by
10383abeffbSHendrik Brueckner	 * calculating the memory offset for the specified mask value.
10483abeffbSHendrik Brueckner	 * Mask value can be any constant.  The macro shifts the mask
10583abeffbSHendrik Brueckner	 * value to calculate the memory offset for the test-under-mask
10683abeffbSHendrik Brueckner	 * instruction.
10783abeffbSHendrik Brueckner	 */
10883abeffbSHendrik Brueckner	.macro TSTMSK addr, mask, size=8, bytepos=0
10983abeffbSHendrik Brueckner		.if (\bytepos < \size) && (\mask >> 8)
11083abeffbSHendrik Brueckner			.if (\mask & 0xff)
11183abeffbSHendrik Brueckner				.error "Mask exceeds byte boundary"
11283abeffbSHendrik Brueckner			.endif
11383abeffbSHendrik Brueckner			TSTMSK \addr, "(\mask >> 8)", \size, "(\bytepos + 1)"
11483abeffbSHendrik Brueckner			.exitm
11583abeffbSHendrik Brueckner		.endif
11683abeffbSHendrik Brueckner		.ifeq \mask
11783abeffbSHendrik Brueckner			.error "Mask must not be zero"
11883abeffbSHendrik Brueckner		.endif
11983abeffbSHendrik Brueckner		off = \size - \bytepos - 1
12083abeffbSHendrik Brueckner		tm	off+\addr, \mask
12183abeffbSHendrik Brueckner	.endm
12283abeffbSHendrik Brueckner
123d768bd89SMartin Schwidefsky	.macro BPOFF
124b058661aSMartin Schwidefsky	ALTERNATIVE "", ".long 0xb2e8c000", 82
125d768bd89SMartin Schwidefsky	.endm
126d768bd89SMartin Schwidefsky
127d768bd89SMartin Schwidefsky	.macro BPON
128b058661aSMartin Schwidefsky	ALTERNATIVE "", ".long 0xb2e8d000", 82
129d768bd89SMartin Schwidefsky	.endm
130d768bd89SMartin Schwidefsky
1316b73044bSMartin Schwidefsky	.macro BPENTER tif_ptr,tif_mask
132b058661aSMartin Schwidefsky	ALTERNATIVE "TSTMSK \tif_ptr,\tif_mask; jz .+8; .long 0xb2e8d000", \
133b058661aSMartin Schwidefsky		    "", 82
1346b73044bSMartin Schwidefsky	.endm
1356b73044bSMartin Schwidefsky
1366b73044bSMartin Schwidefsky	.macro BPEXIT tif_ptr,tif_mask
1376b73044bSMartin Schwidefsky	TSTMSK	\tif_ptr,\tif_mask
138b058661aSMartin Schwidefsky	ALTERNATIVE "jz .+8;  .long 0xb2e8c000", \
139b058661aSMartin Schwidefsky		    "jnz .+8; .long 0xb2e8d000", 82
1406b73044bSMartin Schwidefsky	.endm
1416b73044bSMartin Schwidefsky
142d35925b3SAlexander Gordeev	/*
143d35925b3SAlexander Gordeev	 * The CHKSTG macro jumps to the provided label in case the
144d35925b3SAlexander Gordeev	 * machine check interruption code reports one of unrecoverable
145d35925b3SAlexander Gordeev	 * storage errors:
146d35925b3SAlexander Gordeev	 * - Storage error uncorrected
147d35925b3SAlexander Gordeev	 * - Storage key error uncorrected
148d35925b3SAlexander Gordeev	 * - Storage degradation with Failing-storage-address validity
149d35925b3SAlexander Gordeev	 */
150d35925b3SAlexander Gordeev	.macro CHKSTG errlabel
151d35925b3SAlexander Gordeev	TSTMSK	__LC_MCCK_CODE,(MCCK_CODE_STG_ERROR|MCCK_CODE_STG_KEY_ERROR)
152d35925b3SAlexander Gordeev	jnz	\errlabel
153d35925b3SAlexander Gordeev	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_STG_DEGRAD
15415256194SHeiko Carstens	jz	.Loklabel\@
155d35925b3SAlexander Gordeev	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_STG_FAIL_ADDR
156d35925b3SAlexander Gordeev	jnz	\errlabel
15715256194SHeiko Carstens.Loklabel\@:
158d35925b3SAlexander Gordeev	.endm
159d35925b3SAlexander Gordeev
160b5415c8fSAlexander Gordeev#if IS_ENABLED(CONFIG_KVM)
161b5415c8fSAlexander Gordeev	/*
162b5415c8fSAlexander Gordeev	 * The OUTSIDE macro jumps to the provided label in case the value
163b5415c8fSAlexander Gordeev	 * in the provided register is outside of the provided range. The
164b5415c8fSAlexander Gordeev	 * macro is useful for checking whether a PSW stored in a register
165b5415c8fSAlexander Gordeev	 * pair points inside or outside of a block of instructions.
166b5415c8fSAlexander Gordeev	 * @reg: register to check
167b5415c8fSAlexander Gordeev	 * @start: start of the range
168b5415c8fSAlexander Gordeev	 * @end: end of the range
169b5415c8fSAlexander Gordeev	 * @outside_label: jump here if @reg is outside of [@start..@end)
170b5415c8fSAlexander Gordeev	 */
171b5415c8fSAlexander Gordeev	.macro OUTSIDE reg,start,end,outside_label
172b5415c8fSAlexander Gordeev	lgr	%r14,\reg
173b5415c8fSAlexander Gordeev	larl	%r13,\start
174b5415c8fSAlexander Gordeev	slgr	%r14,%r13
175b5415c8fSAlexander Gordeev	lghi	%r13,\end - \start
176b5415c8fSAlexander Gordeev	clgr	%r14,%r13
177b5415c8fSAlexander Gordeev	jhe	\outside_label
178b5415c8fSAlexander Gordeev	.endm
179fbbdfca5SAlexander Gordeev
180fbbdfca5SAlexander Gordeev	.macro SIEEXIT
181fbbdfca5SAlexander Gordeev	lg	%r9,__SF_SIE_CONTROL(%r15)	# get control block pointer
182fbbdfca5SAlexander Gordeev	ni	__SIE_PROG0C+3(%r9),0xfe	# no longer in SIE
183fbbdfca5SAlexander Gordeev	lctlg	%c1,%c1,__LC_KERNEL_ASCE	# load primary asce
184fbbdfca5SAlexander Gordeev	larl	%r9,sie_exit			# skip forward to sie_exit
185fbbdfca5SAlexander Gordeev	.endm
186b5415c8fSAlexander Gordeev#endif
187b5415c8fSAlexander Gordeev
1886dd85fbbSMartin Schwidefsky	GEN_BR_THUNK %r14
189f19fbd5eSMartin Schwidefsky
1904bfc86ceSHeiko Carstens	.section .kprobes.text, "ax"
19146210c44SHeiko Carstens.Ldummy:
19246210c44SHeiko Carstens	/*
19356e62a73SSven Schnelle	 * This nop exists only in order to avoid that __bpon starts at
19446210c44SHeiko Carstens	 * the beginning of the kprobes text section. In that case we would
19546210c44SHeiko Carstens	 * have several symbols at the same address. E.g. objdump would take
19646210c44SHeiko Carstens	 * an arbitrary symbol name when disassembling this code.
19756e62a73SSven Schnelle	 * With the added nop in between the __bpon symbol is unique
19846210c44SHeiko Carstens	 * again.
19946210c44SHeiko Carstens	 */
20046210c44SHeiko Carstens	nop	0
2014bfc86ceSHeiko Carstens
202d768bd89SMartin SchwidefskyENTRY(__bpon)
203d768bd89SMartin Schwidefsky	.globl __bpon
204d768bd89SMartin Schwidefsky	BPON
2056dd85fbbSMartin Schwidefsky	BR_EX	%r14
20626a374aeSMartin SchwidefskyENDPROC(__bpon)
207d768bd89SMartin Schwidefsky
2084bfc86ceSHeiko Carstens/*
2094bfc86ceSHeiko Carstens * Scheduler resume function, called by switch_to
2104bfc86ceSHeiko Carstens *  gpr2 = (task_struct *) prev
2114bfc86ceSHeiko Carstens *  gpr3 = (task_struct *) next
2124bfc86ceSHeiko Carstens * Returns:
2134bfc86ceSHeiko Carstens *  gpr2 = prev
2144bfc86ceSHeiko Carstens */
2154bfc86ceSHeiko CarstensENTRY(__switch_to)
2164bfc86ceSHeiko Carstens	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
2173241d3ebSHeiko Carstens	lghi	%r4,__TASK_stack
2183241d3ebSHeiko Carstens	lghi	%r1,__TASK_thread
2199fed920eSVasily Gorbik	llill	%r5,STACK_INIT
2203241d3ebSHeiko Carstens	stg	%r15,__THREAD_ksp(%r1,%r2)	# store kernel stack of prev
2219fed920eSVasily Gorbik	lg	%r15,0(%r4,%r3)			# start of kernel stack of next
2229fed920eSVasily Gorbik	agr	%r15,%r5			# end of kernel stack of next
2234bfc86ceSHeiko Carstens	stg	%r3,__LC_CURRENT		# store task struct of next
2244bfc86ceSHeiko Carstens	stg	%r15,__LC_KERNEL_STACK		# store end of kernel stack
2253241d3ebSHeiko Carstens	lg	%r15,__THREAD_ksp(%r1,%r3)	# load kernel stack of next
2263241d3ebSHeiko Carstens	aghi	%r3,__TASK_pid
2273241d3ebSHeiko Carstens	mvc	__LC_CURRENT_PID(4,%r0),0(%r3)	# store pid of next
2284bfc86ceSHeiko Carstens	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
229e5b98199SMartin Schwidefsky	ALTERNATIVE "", ".insn s,0xb2800000,_LPP_OFFSET", 40
2306dd85fbbSMartin Schwidefsky	BR_EX	%r14
23126a374aeSMartin SchwidefskyENDPROC(__switch_to)
2324bfc86ceSHeiko Carstens
233d0fc4107SMartin Schwidefsky#if IS_ENABLED(CONFIG_KVM)
234d0fc4107SMartin Schwidefsky/*
235d0fc4107SMartin Schwidefsky * sie64a calling convention:
236d0fc4107SMartin Schwidefsky * %r2 pointer to sie control block
237d0fc4107SMartin Schwidefsky * %r3 guest register save area
238d0fc4107SMartin Schwidefsky */
239d0fc4107SMartin SchwidefskyENTRY(sie64a)
240d0fc4107SMartin Schwidefsky	stmg	%r6,%r14,__SF_GPRS(%r15)	# save kernel registers
2416b73044bSMartin Schwidefsky	lg	%r12,__LC_CURRENT
24292fa7a13SMartin Schwidefsky	stg	%r2,__SF_SIE_CONTROL(%r15)	# save control block pointer
24392fa7a13SMartin Schwidefsky	stg	%r3,__SF_SIE_SAVEAREA(%r15)	# save guest register save area
24492fa7a13SMartin Schwidefsky	xc	__SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0
24592fa7a13SMartin Schwidefsky	mvc	__SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags
246d0fc4107SMartin Schwidefsky	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
247d0fc4107SMartin Schwidefsky	lg	%r14,__LC_GMAP			# get gmap pointer
248d0fc4107SMartin Schwidefsky	ltgr	%r14,%r14
249d0fc4107SMartin Schwidefsky	jz	.Lsie_gmap
250d0fc4107SMartin Schwidefsky	lctlg	%c1,%c1,__GMAP_ASCE(%r14)	# load primary asce
251d0fc4107SMartin Schwidefsky.Lsie_gmap:
25292fa7a13SMartin Schwidefsky	lg	%r14,__SF_SIE_CONTROL(%r15)	# get control block pointer
253d0fc4107SMartin Schwidefsky	oi	__SIE_PROG0C+3(%r14),1		# we are going into SIE now
254d0fc4107SMartin Schwidefsky	tm	__SIE_PROG20+3(%r14),3		# last exit...
255d0fc4107SMartin Schwidefsky	jnz	.Lsie_skip
25683abeffbSHendrik Brueckner	TSTMSK	__LC_CPU_FLAGS,_CIF_FPU
257d0fc4107SMartin Schwidefsky	jo	.Lsie_skip			# exit if fp/vx regs changed
25892fa7a13SMartin Schwidefsky	BPEXIT	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
259c929500dSQingFeng Hao.Lsie_entry:
260d0fc4107SMartin Schwidefsky	sie	0(%r14)
261d768bd89SMartin Schwidefsky	BPOFF
26292fa7a13SMartin Schwidefsky	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
263d0fc4107SMartin Schwidefsky.Lsie_skip:
264d0fc4107SMartin Schwidefsky	ni	__SIE_PROG0C+3(%r14),0xfe	# no longer in SIE
26587d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE	# load primary asce
266d0fc4107SMartin Schwidefsky.Lsie_done:
267d0fc4107SMartin Schwidefsky# some program checks are suppressing. C code (e.g. do_protection_exception)
268c0e7bb38SChristian Borntraeger# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
269c0e7bb38SChristian Borntraeger# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
270c0e7bb38SChristian Borntraeger# Other instructions between sie64a and .Lsie_done should not cause program
271c0e7bb38SChristian Borntraeger# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
272c0e7bb38SChristian Borntraeger.Lrewind_pad6:
273c0e7bb38SChristian Borntraeger	nopr	7
274c0e7bb38SChristian Borntraeger.Lrewind_pad4:
275c0e7bb38SChristian Borntraeger	nopr	7
276c0e7bb38SChristian Borntraeger.Lrewind_pad2:
277c0e7bb38SChristian Borntraeger	nopr	7
278d0fc4107SMartin Schwidefsky	.globl sie_exit
279d0fc4107SMartin Schwidefskysie_exit:
28092fa7a13SMartin Schwidefsky	lg	%r14,__SF_SIE_SAVEAREA(%r15)	# load guest register save area
281d0fc4107SMartin Schwidefsky	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
2827041d281SMartin Schwidefsky	xgr	%r0,%r0				# clear guest registers to
2837041d281SMartin Schwidefsky	xgr	%r1,%r1				# prevent speculative use
2847041d281SMartin Schwidefsky	xgr	%r3,%r3
2857041d281SMartin Schwidefsky	xgr	%r4,%r4
2867041d281SMartin Schwidefsky	xgr	%r5,%r5
287d0fc4107SMartin Schwidefsky	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
28892fa7a13SMartin Schwidefsky	lg	%r2,__SF_SIE_REASON(%r15)	# return exit reason code
2896dd85fbbSMartin Schwidefsky	BR_EX	%r14
290d0fc4107SMartin Schwidefsky.Lsie_fault:
291d0fc4107SMartin Schwidefsky	lghi	%r14,-EFAULT
29292fa7a13SMartin Schwidefsky	stg	%r14,__SF_SIE_REASON(%r15)	# set exit reason code
293d0fc4107SMartin Schwidefsky	j	sie_exit
294d0fc4107SMartin Schwidefsky
295c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad6,.Lsie_fault)
296c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad4,.Lsie_fault)
297c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad2,.Lsie_fault)
298d0fc4107SMartin Schwidefsky	EX_TABLE(sie_exit,.Lsie_fault)
29926a374aeSMartin SchwidefskyENDPROC(sie64a)
300711f5df7SAl ViroEXPORT_SYMBOL(sie64a)
301711f5df7SAl ViroEXPORT_SYMBOL(sie_exit)
302d0fc4107SMartin Schwidefsky#endif
303d0fc4107SMartin Schwidefsky
3044bfc86ceSHeiko Carstens/*
3054bfc86ceSHeiko Carstens * SVC interrupt handler routine. System calls are synchronous events and
3067b7735c5SChristian Borntraeger * are entered with interrupts disabled.
3074bfc86ceSHeiko Carstens */
3084bfc86ceSHeiko Carstens
3094bfc86ceSHeiko CarstensENTRY(system_call)
31056e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
3114bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
312d768bd89SMartin Schwidefsky	BPOFF
31356e62a73SSven Schnelle	lghi	%r14,0
3144bfc86ceSHeiko Carstens.Lsysc_per:
3153b051e89SSven Schnelle	STBEAR	__LC_LAST_BREAK
31687d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
31756e62a73SSven Schnelle	lg	%r12,__LC_CURRENT
3184bfc86ceSHeiko Carstens	lg	%r15,__LC_KERNEL_STACK
3199365965dSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
32056e62a73SSven Schnelle	stmg	%r0,%r7,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
32156e62a73SSven Schnelle	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
322d3f46896SChristian Borntraeger	# clear user controlled register to prevent speculative use
323d3f46896SChristian Borntraeger	xgr	%r0,%r0
32456e62a73SSven Schnelle	xgr	%r1,%r1
32556e62a73SSven Schnelle	xgr	%r4,%r4
32656e62a73SSven Schnelle	xgr	%r5,%r5
32756e62a73SSven Schnelle	xgr	%r6,%r6
32856e62a73SSven Schnelle	xgr	%r7,%r7
32956e62a73SSven Schnelle	xgr	%r8,%r8
33056e62a73SSven Schnelle	xgr	%r9,%r9
33156e62a73SSven Schnelle	xgr	%r10,%r10
33256e62a73SSven Schnelle	xgr	%r11,%r11
33356e62a73SSven Schnelle	la	%r2,STACK_FRAME_OVERHEAD(%r15)	# pointer to pt_regs
334af9ad822SSven Schnelle	mvc	__PT_R8(64,%r2),__LC_SAVE_AREA_SYNC
3353b051e89SSven Schnelle	MBEAR	%r2
33656e62a73SSven Schnelle	lgr	%r3,%r14
33756e62a73SSven Schnelle	brasl	%r14,__do_syscall
33887d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_USER_ASCE
33956e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
3406b73044bSMartin Schwidefsky	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3413b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
34256e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
3434bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
3443b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
34526a374aeSMartin SchwidefskyENDPROC(system_call)
3464bfc86ceSHeiko Carstens
3474bfc86ceSHeiko Carstens#
3484bfc86ceSHeiko Carstens# a new process exits the kernel with ret_from_fork
3494bfc86ceSHeiko Carstens#
3504bfc86ceSHeiko CarstensENTRY(ret_from_fork)
35156e62a73SSven Schnelle	lgr	%r3,%r11
35256e62a73SSven Schnelle	brasl	%r14,__ret_from_fork
35356e62a73SSven Schnelle	lctlg	%c1,%c1,__LC_USER_ASCE
35456e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
35556e62a73SSven Schnelle	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3563b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
35756e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
35856e62a73SSven Schnelle	stpt	__LC_EXIT_TIMER
3593b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
36026a374aeSMartin SchwidefskyENDPROC(ret_from_fork)
36126a374aeSMartin Schwidefsky
3624bfc86ceSHeiko Carstens/*
3634bfc86ceSHeiko Carstens * Program check handler routine
3644bfc86ceSHeiko Carstens */
3654bfc86ceSHeiko Carstens
3664bfc86ceSHeiko CarstensENTRY(pgm_check_handler)
36756e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
368d768bd89SMartin Schwidefsky	BPOFF
3694bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
37056e62a73SSven Schnelle	lg	%r12,__LC_CURRENT
37156e62a73SSven Schnelle	lghi	%r10,0
3724bfc86ceSHeiko Carstens	lmg	%r8,%r9,__LC_PGM_OLD_PSW
37387d59863SHeiko Carstens	tmhh	%r8,0x0001		# coming from user space?
37487d59863SHeiko Carstens	jno	.Lpgm_skip_asce
37587d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
37656e62a73SSven Schnelle	j	3f			# -> fault in user space
37787d59863SHeiko Carstens.Lpgm_skip_asce:
378d0fc4107SMartin Schwidefsky#if IS_ENABLED(CONFIG_KVM)
3790a5e2ec2SMartin Schwidefsky	# cleanup critical section for program checks in sie64a
380b5415c8fSAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,1f
381fbbdfca5SAlexander Gordeev	SIEEXIT
38256e62a73SSven Schnelle	lghi	%r10,_PIF_GUEST_FAULT
383d0fc4107SMartin Schwidefsky#endif
3840b38b5e1SSven Schnelle1:	tmhh	%r8,0x4000		# PER bit set in old PSW ?
3850b38b5e1SSven Schnelle	jnz	2f			# -> enabled, can't be a double fault
3864bfc86ceSHeiko Carstens	tm	__LC_PGM_ILC+3,0x80	# check for per exception
3874bfc86ceSHeiko Carstens	jnz	.Lpgm_svcper		# -> single stepped svc
3880b38b5e1SSven Schnelle2:	CHECK_STACK __LC_SAVE_AREA_SYNC
3894bfc86ceSHeiko Carstens	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
39056e62a73SSven Schnelle	# CHECK_VMAP_STACK branches to stack_overflow or 4f
39156e62a73SSven Schnelle	CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f
39256e62a73SSven Schnelle3:	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
3934bfc86ceSHeiko Carstens	lg	%r15,__LC_KERNEL_STACK
39456e62a73SSven Schnelle4:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
39556e62a73SSven Schnelle	stg	%r10,__PT_FLAGS(%r11)
39656e62a73SSven Schnelle	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
3974bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
39856e62a73SSven Schnelle	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
3993b051e89SSven Schnelle	mvc	__PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
40056e62a73SSven Schnelle	stmg	%r8,%r9,__PT_PSW(%r11)
40156e62a73SSven Schnelle
4027041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
4037041d281SMartin Schwidefsky	xgr	%r0,%r0
4047041d281SMartin Schwidefsky	xgr	%r1,%r1
4057041d281SMartin Schwidefsky	xgr	%r3,%r3
4067041d281SMartin Schwidefsky	xgr	%r4,%r4
4077041d281SMartin Schwidefsky	xgr	%r5,%r5
4087041d281SMartin Schwidefsky	xgr	%r6,%r6
4097041d281SMartin Schwidefsky	xgr	%r7,%r7
41056e62a73SSven Schnelle	lgr	%r2,%r11
41156e62a73SSven Schnelle	brasl	%r14,__do_pgm_check
41256e62a73SSven Schnelle	tmhh	%r8,0x0001		# returning to user space?
41356e62a73SSven Schnelle	jno	.Lpgm_exit_kernel
41456e62a73SSven Schnelle	lctlg	%c1,%c1,__LC_USER_ASCE
41556e62a73SSven Schnelle	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
4160cd9b723SHeiko Carstens	stpt	__LC_EXIT_TIMER
41756e62a73SSven Schnelle.Lpgm_exit_kernel:
41856e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
4193b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
42056e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
4213b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
4224bfc86ceSHeiko Carstens
4234bfc86ceSHeiko Carstens#
4244bfc86ceSHeiko Carstens# single stepped system call
4254bfc86ceSHeiko Carstens#
4264bfc86ceSHeiko Carstens.Lpgm_svcper:
4274bfc86ceSHeiko Carstens	mvc	__LC_RETURN_PSW(8),__LC_SVC_NEW_PSW
4284bfc86ceSHeiko Carstens	larl	%r14,.Lsysc_per
4294bfc86ceSHeiko Carstens	stg	%r14,__LC_RETURN_PSW+8
43056e62a73SSven Schnelle	lghi	%r14,1
4313b051e89SSven Schnelle	LBEAR	__LC_PGM_LAST_BREAK
4323b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE # branch to .Lsysc_per
43326a374aeSMartin SchwidefskyENDPROC(pgm_check_handler)
4344bfc86ceSHeiko Carstens
4354bfc86ceSHeiko Carstens/*
43656e62a73SSven Schnelle * Interrupt handler macro used for external and IO interrupts.
4374bfc86ceSHeiko Carstens */
43856e62a73SSven Schnelle.macro INT_HANDLER name,lc_old_psw,handler
43956e62a73SSven SchnelleENTRY(\name)
440*10bc15baSVasily Gorbik	stckf	__LC_INT_CLOCK
44156e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
4423b051e89SSven Schnelle	STBEAR	__LC_LAST_BREAK
443d768bd89SMartin Schwidefsky	BPOFF
4444bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
445d5c352cdSHeiko Carstens	lg	%r12,__LC_CURRENT
44656e62a73SSven Schnelle	lmg	%r8,%r9,\lc_old_psw
447b0d31159SSven Schnelle	tmhh	%r8,0x0001			# interrupting from user ?
448b0d31159SSven Schnelle	jnz	1f
449b0d31159SSven Schnelle#if IS_ENABLED(CONFIG_KVM)
450b5415c8fSAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,0f
451fbbdfca5SAlexander Gordeev	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
452fbbdfca5SAlexander Gordeev	SIEEXIT
453b0d31159SSven Schnelle#endif
454b0d31159SSven Schnelle0:	CHECK_STACK __LC_SAVE_AREA_ASYNC
455b0d31159SSven Schnelle	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
456b0d31159SSven Schnelle	j	2f
457b0d31159SSven Schnelle1:	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
458b0d31159SSven Schnelle	lctlg	%c1,%c1,__LC_KERNEL_ASCE
459b0d31159SSven Schnelle	lg	%r15,__LC_KERNEL_STACK
460b74e409eSVasily Gorbik2:	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
461b74e409eSVasily Gorbik	la	%r11,STACK_FRAME_OVERHEAD(%r15)
4624bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
4637041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
4647041d281SMartin Schwidefsky	xgr	%r0,%r0
4657041d281SMartin Schwidefsky	xgr	%r1,%r1
4667041d281SMartin Schwidefsky	xgr	%r3,%r3
4677041d281SMartin Schwidefsky	xgr	%r4,%r4
4687041d281SMartin Schwidefsky	xgr	%r5,%r5
4697041d281SMartin Schwidefsky	xgr	%r6,%r6
4707041d281SMartin Schwidefsky	xgr	%r7,%r7
4717041d281SMartin Schwidefsky	xgr	%r10,%r10
472ca1f4d70SSven Schnelle	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
4734bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
4743b051e89SSven Schnelle	MBEAR	%r11
4754bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
47656e62a73SSven Schnelle	tm	%r8,0x0001		# coming from user space?
47756e62a73SSven Schnelle	jno	1f
47887d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
47956e62a73SSven Schnelle1:	lgr	%r2,%r11		# pass pointer to pt_regs
48056e62a73SSven Schnelle	brasl	%r14,\handler
4814bfc86ceSHeiko Carstens	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r11)
48256e62a73SSven Schnelle	tmhh	%r8,0x0001		# returning to user ?
48356e62a73SSven Schnelle	jno	2f
48487d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_USER_ASCE
4856b73044bSMartin Schwidefsky	BPEXIT	__TI_flags(%r12),_TIF_ISOLATE_BP
4864bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
4873b051e89SSven Schnelle2:	LBEAR	__PT_LAST_BREAK(%r11)
4883b051e89SSven Schnelle	lmg	%r0,%r15,__PT_R0(%r11)
4893b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
49056e62a73SSven SchnelleENDPROC(\name)
49156e62a73SSven Schnelle.endm
4924bfc86ceSHeiko Carstens
49356e62a73SSven SchnelleINT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
49456e62a73SSven SchnelleINT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
4954bfc86ceSHeiko Carstens
4964bfc86ceSHeiko Carstens/*
4970b0ed657SSven Schnelle * Load idle PSW.
4984bfc86ceSHeiko Carstens */
4994bfc86ceSHeiko CarstensENTRY(psw_idle)
500a994eddbSVasily Gorbik	stg	%r14,(__SF_GPRS+8*8)(%r15)
5014bfc86ceSHeiko Carstens	stg	%r3,__SF_EMPTY(%r15)
50256e62a73SSven Schnelle	larl	%r1,psw_idle_exit
5034bfc86ceSHeiko Carstens	stg	%r1,__SF_EMPTY+8(%r15)
50472d38b19SMartin Schwidefsky	larl	%r1,smp_cpu_mtid
50572d38b19SMartin Schwidefsky	llgf	%r1,0(%r1)
50672d38b19SMartin Schwidefsky	ltgr	%r1,%r1
50772d38b19SMartin Schwidefsky	jz	.Lpsw_idle_stcctm
50856e62a73SSven Schnelle	.insn	rsy,0xeb0000000017,%r1,5,__MT_CYCLES_ENTER(%r2)
50972d38b19SMartin Schwidefsky.Lpsw_idle_stcctm:
510419123f9SMartin Schwidefsky	oi	__LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT
511d768bd89SMartin Schwidefsky	BPON
512*10bc15baSVasily Gorbik	stckf	__CLOCK_IDLE_ENTER(%r2)
5134bfc86ceSHeiko Carstens	stpt	__TIMER_IDLE_ENTER(%r2)
5144bfc86ceSHeiko Carstens	lpswe	__SF_EMPTY(%r15)
51556e62a73SSven Schnelle.globl psw_idle_exit
51656e62a73SSven Schnellepsw_idle_exit:
5176dd85fbbSMartin Schwidefsky	BR_EX	%r14
51826a374aeSMartin SchwidefskyENDPROC(psw_idle)
5194bfc86ceSHeiko Carstens
520b5510d9bSHendrik Brueckner/*
5214bfc86ceSHeiko Carstens * Machine check handler routines
5224bfc86ceSHeiko Carstens */
5234bfc86ceSHeiko CarstensENTRY(mcck_int_handler)
524*10bc15baSVasily Gorbik	stckf	__LC_MCCK_CLOCK
525d768bd89SMartin Schwidefsky	BPOFF
5263037a52fSMartin Schwidefsky	la	%r1,4095		# validate r1
5273037a52fSMartin Schwidefsky	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# validate cpu timer
5283b051e89SSven Schnelle	LBEAR	__LC_LAST_BREAK_SAVE_AREA-4095(%r1)		# validate bear
5293037a52fSMartin Schwidefsky	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# validate gprs
530d5c352cdSHeiko Carstens	lg	%r12,__LC_CURRENT
5314bfc86ceSHeiko Carstens	lmg	%r8,%r9,__LC_MCK_OLD_PSW
53283abeffbSHendrik Brueckner	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE
5334bfc86ceSHeiko Carstens	jo	.Lmcck_panic		# yes -> rest of mcck code invalid
5343037a52fSMartin Schwidefsky	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_CR_VALID
5353037a52fSMartin Schwidefsky	jno	.Lmcck_panic		# control registers invalid -> panic
5363037a52fSMartin Schwidefsky	la	%r14,4095
5373037a52fSMartin Schwidefsky	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r14) # validate ctl regs
5383037a52fSMartin Schwidefsky	ptlb
5395fa2ea07SAlexander Gordeev	lghi	%r14,__LC_CPU_TIMER_SAVE_AREA
5404bfc86ceSHeiko Carstens	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
54183abeffbSHendrik Brueckner	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID
5424bfc86ceSHeiko Carstens	jo	3f
54356e62a73SSven Schnelle	la	%r14,__LC_SYS_ENTER_TIMER
54456e62a73SSven Schnelle	clc	0(8,%r14),__LC_EXIT_TIMER
5454bfc86ceSHeiko Carstens	jl	1f
5464bfc86ceSHeiko Carstens	la	%r14,__LC_EXIT_TIMER
5474bfc86ceSHeiko Carstens1:	clc	0(8,%r14),__LC_LAST_UPDATE_TIMER
5484bfc86ceSHeiko Carstens	jl	2f
5494bfc86ceSHeiko Carstens	la	%r14,__LC_LAST_UPDATE_TIMER
5504bfc86ceSHeiko Carstens2:	spt	0(%r14)
5514bfc86ceSHeiko Carstens	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
5523037a52fSMartin Schwidefsky3:	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_PSW_MWP_VALID
5533037a52fSMartin Schwidefsky	jno	.Lmcck_panic
5543037a52fSMartin Schwidefsky	tmhh	%r8,0x0001		# interrupting from user ?
555d35925b3SAlexander Gordeev	jnz	6f
5563037a52fSMartin Schwidefsky	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID
5573037a52fSMartin Schwidefsky	jno	.Lmcck_panic
558b0d31159SSven Schnelle#if IS_ENABLED(CONFIG_KVM)
559d35925b3SAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,6f
560d35925b3SAlexander Gordeev	OUTSIDE	%r9,.Lsie_entry,.Lsie_skip,4f
56120232b18SAlexander Gordeev	oi	__LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
562d35925b3SAlexander Gordeev	j	5f
563d35925b3SAlexander Gordeev4:	CHKSTG	.Lmcck_panic
564d35925b3SAlexander Gordeev5:	larl	%r14,.Lstosm_tmp
565d35925b3SAlexander Gordeev	stosm	0(%r14),0x04		# turn dat on, keep irqs off
566d35925b3SAlexander Gordeev	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
567fbbdfca5SAlexander Gordeev	SIEEXIT
568b61b1595SSven Schnelle	j	.Lmcck_stack
569e2c13d64SAlexander Gordeev#endif
570d35925b3SAlexander Gordeev6:	CHKSTG	.Lmcck_panic
571d35925b3SAlexander Gordeev	larl	%r14,.Lstosm_tmp
572d35925b3SAlexander Gordeev	stosm	0(%r14),0x04		# turn dat on, keep irqs off
573d35925b3SAlexander Gordeev	tmhh	%r8,0x0001		# interrupting from user ?
574d35925b3SAlexander Gordeev	jz	.Lmcck_stack
575b0d31159SSven Schnelle	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
576b61b1595SSven Schnelle.Lmcck_stack:
577b61b1595SSven Schnelle	lg	%r15,__LC_MCCK_STACK
578b61b1595SSven Schnelle	la	%r11,STACK_FRAME_OVERHEAD(%r15)
57926521412SSven Schnelle	stctg	%c1,%c1,__PT_CR1(%r11)
580b61b1595SSven Schnelle	lctlg	%c1,%c1,__LC_KERNEL_ASCE
581b61b1595SSven Schnelle	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
5824bfc86ceSHeiko Carstens	lghi	%r14,__LC_GPREGS_SAVE_AREA+64
5834bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
5847041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
5857041d281SMartin Schwidefsky	xgr	%r0,%r0
5867041d281SMartin Schwidefsky	xgr	%r1,%r1
5877041d281SMartin Schwidefsky	xgr	%r3,%r3
5887041d281SMartin Schwidefsky	xgr	%r4,%r4
5897041d281SMartin Schwidefsky	xgr	%r5,%r5
5907041d281SMartin Schwidefsky	xgr	%r6,%r6
5917041d281SMartin Schwidefsky	xgr	%r7,%r7
5927041d281SMartin Schwidefsky	xgr	%r10,%r10
5934bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),0(%r14)
5944bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
5954bfc86ceSHeiko Carstens	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
5964bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
5974bfc86ceSHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
5984bfc86ceSHeiko Carstens	brasl	%r14,s390_do_machine_check
5990b0ed657SSven Schnelle	cghi	%r2,0
6000b0ed657SSven Schnelle	je	.Lmcck_return
6014bfc86ceSHeiko Carstens	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
6024bfc86ceSHeiko Carstens	mvc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
6034bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
6044bfc86ceSHeiko Carstens	la	%r11,STACK_FRAME_OVERHEAD(%r1)
6054bfc86ceSHeiko Carstens	lgr	%r15,%r1
6064bfc86ceSHeiko Carstens	brasl	%r14,s390_handle_mcck
6074bfc86ceSHeiko Carstens.Lmcck_return:
60887d59863SHeiko Carstens	lctlg	%c1,%c1,__PT_CR1(%r11)
6094bfc86ceSHeiko Carstens	lmg	%r0,%r10,__PT_R0(%r11)
6104bfc86ceSHeiko Carstens	mvc	__LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
6114bfc86ceSHeiko Carstens	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
6124bfc86ceSHeiko Carstens	jno	0f
6136b73044bSMartin Schwidefsky	BPEXIT	__TI_flags(%r12),_TIF_ISOLATE_BP
6144bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
6153b051e89SSven Schnelle0:	ALTERNATIVE "", __stringify(lghi %r12,__LC_LAST_BREAK_SAVE_AREA),193
6163b051e89SSven Schnelle	LBEAR	0(%r12)
6173b051e89SSven Schnelle	lmg	%r11,%r15,__PT_R11(%r11)
6183b051e89SSven Schnelle	LPSWEY	__LC_RETURN_MCCK_PSW,__LC_RETURN_MCCK_LPSWE
6194bfc86ceSHeiko Carstens
6204bfc86ceSHeiko Carstens.Lmcck_panic:
6217f6dc8d4SAlexander Gordeev	/*
6227f6dc8d4SAlexander Gordeev	 * Iterate over all possible CPU addresses in the range 0..0xffff
6237f6dc8d4SAlexander Gordeev	 * and stop each CPU using signal processor. Use compare and swap
6247f6dc8d4SAlexander Gordeev	 * to allow just one CPU-stopper and prevent concurrent CPUs from
6257f6dc8d4SAlexander Gordeev	 * stopping each other while leaving the others running.
6267f6dc8d4SAlexander Gordeev	 */
6277f6dc8d4SAlexander Gordeev	lhi	%r5,0
6287f6dc8d4SAlexander Gordeev	lhi	%r6,1
6297f6dc8d4SAlexander Gordeev	larl	%r7,.Lstop_lock
6307f6dc8d4SAlexander Gordeev	cs	%r5,%r6,0(%r7)		# single CPU-stopper only
6317f6dc8d4SAlexander Gordeev	jnz	4f
6327f6dc8d4SAlexander Gordeev	larl	%r7,.Lthis_cpu
6337f6dc8d4SAlexander Gordeev	stap	0(%r7)			# this CPU address
6347f6dc8d4SAlexander Gordeev	lh	%r4,0(%r7)
6357f6dc8d4SAlexander Gordeev	nilh	%r4,0
6367f6dc8d4SAlexander Gordeev	lhi	%r0,1
6377f6dc8d4SAlexander Gordeev	sll	%r0,16			# CPU counter
6387f6dc8d4SAlexander Gordeev	lhi	%r3,0			# next CPU address
6397f6dc8d4SAlexander Gordeev0:	cr	%r3,%r4
6407f6dc8d4SAlexander Gordeev	je	2f
6417f6dc8d4SAlexander Gordeev1:	sigp	%r1,%r3,SIGP_STOP	# stop next CPU
6427f6dc8d4SAlexander Gordeev	brc	SIGP_CC_BUSY,1b
6437f6dc8d4SAlexander Gordeev2:	ahi	%r3,1
6447f6dc8d4SAlexander Gordeev	brct	%r0,0b
6457f6dc8d4SAlexander Gordeev3:	sigp	%r1,%r4,SIGP_STOP	# stop this CPU
6467f6dc8d4SAlexander Gordeev	brc	SIGP_CC_BUSY,3b
6477f6dc8d4SAlexander Gordeev4:	j	4b
64826a374aeSMartin SchwidefskyENDPROC(mcck_int_handler)
6494bfc86ceSHeiko Carstens
6504bfc86ceSHeiko CarstensENTRY(restart_int_handler)
651e5b98199SMartin Schwidefsky	ALTERNATIVE "", ".insn s,0xb2800000,_LPP_OFFSET", 40
652e5b98199SMartin Schwidefsky	stg	%r15,__LC_SAVE_AREA_RESTART
653915fea04SAlexander Gordeev	TSTMSK	__LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4
654915fea04SAlexander Gordeev	jz	0f
655915fea04SAlexander Gordeev	la	%r15,4095
656915fea04SAlexander Gordeev	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r15)
657915fea04SAlexander Gordeev0:	larl	%r15,.Lstosm_tmp
658915fea04SAlexander Gordeev	stosm	0(%r15),0x04			# turn dat on, keep irqs off
6594bfc86ceSHeiko Carstens	lg	%r15,__LC_RESTART_STACK
660ce3dc447SMartin Schwidefsky	xc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15)
661ce3dc447SMartin Schwidefsky	stmg	%r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
662ce3dc447SMartin Schwidefsky	mvc	STACK_FRAME_OVERHEAD+__PT_R15(8,%r15),__LC_SAVE_AREA_RESTART
663ce3dc447SMartin Schwidefsky	mvc	STACK_FRAME_OVERHEAD+__PT_PSW(16,%r15),__LC_RST_OLD_PSW
6644bfc86ceSHeiko Carstens	xc	0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
6654bfc86ceSHeiko Carstens	lg	%r1,__LC_RESTART_FN		# load fn, parm & source cpu
6664bfc86ceSHeiko Carstens	lg	%r2,__LC_RESTART_DATA
667915fea04SAlexander Gordeev	lgf	%r3,__LC_RESTART_SOURCE
6684bfc86ceSHeiko Carstens	ltgr	%r3,%r3				# test source cpu address
6694bfc86ceSHeiko Carstens	jm	1f				# negative -> skip source stop
6704bfc86ceSHeiko Carstens0:	sigp	%r4,%r3,SIGP_SENSE		# sigp sense to source cpu
6714bfc86ceSHeiko Carstens	brc	10,0b				# wait for status stored
6724bfc86ceSHeiko Carstens1:	basr	%r14,%r1			# call function
6734bfc86ceSHeiko Carstens	stap	__SF_EMPTY(%r15)		# store cpu address
6744bfc86ceSHeiko Carstens	llgh	%r3,__SF_EMPTY(%r15)
6754bfc86ceSHeiko Carstens2:	sigp	%r4,%r3,SIGP_STOP		# sigp stop to current cpu
6764bfc86ceSHeiko Carstens	brc	2,2b
6774bfc86ceSHeiko Carstens3:	j	3b
67826a374aeSMartin SchwidefskyENDPROC(restart_int_handler)
6794bfc86ceSHeiko Carstens
6804bfc86ceSHeiko Carstens	.section .kprobes.text, "ax"
6814bfc86ceSHeiko Carstens
682ce3dc447SMartin Schwidefsky#if defined(CONFIG_CHECK_STACK) || defined(CONFIG_VMAP_STACK)
6834bfc86ceSHeiko Carstens/*
6844bfc86ceSHeiko Carstens * The synchronous or the asynchronous stack overflowed. We are dead.
6854bfc86ceSHeiko Carstens * No need to properly save the registers, we are going to panic anyway.
6864bfc86ceSHeiko Carstens * Setup a pt_regs so that show_trace can provide a good call trace.
6874bfc86ceSHeiko Carstens */
68826a374aeSMartin SchwidefskyENTRY(stack_overflow)
689ce3dc447SMartin Schwidefsky	lg	%r15,__LC_NODAT_STACK	# change to panic stack
6904bfc86ceSHeiko Carstens	la	%r11,STACK_FRAME_OVERHEAD(%r15)
6914bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
6924bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
6934bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),0(%r14)
6944bfc86ceSHeiko Carstens	stg	%r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
6954bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
6964bfc86ceSHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
6974bfc86ceSHeiko Carstens	jg	kernel_stack_overflow
69826a374aeSMartin SchwidefskyENDPROC(stack_overflow)
6994bfc86ceSHeiko Carstens#endif
7004bfc86ceSHeiko Carstens
7017f6dc8d4SAlexander Gordeev	.section .data, "aw"
7027f6dc8d4SAlexander Gordeev		.align	4
7037f6dc8d4SAlexander Gordeev.Lstop_lock:	.long	0
7047f6dc8d4SAlexander Gordeev.Lthis_cpu:	.short	0
705d35925b3SAlexander Gordeev.Lstosm_tmp:	.byte	0
7064bfc86ceSHeiko Carstens	.section .rodata, "a"
707ff4a742dSGerald Schaefer#define SYSCALL(esame,emu)	.quad __s390x_ ## esame
7084bfc86ceSHeiko Carstens	.globl	sys_call_table
7094bfc86ceSHeiko Carstenssys_call_table:
7104381f9f1SHendrik Brueckner#include "asm/syscall_table.h"
7114bfc86ceSHeiko Carstens#undef SYSCALL
7124bfc86ceSHeiko Carstens
7134bfc86ceSHeiko Carstens#ifdef CONFIG_COMPAT
7144bfc86ceSHeiko Carstens
715ff4a742dSGerald Schaefer#define SYSCALL(esame,emu)	.quad __s390_ ## emu
7164bfc86ceSHeiko Carstens	.globl	sys_call_table_emu
7174bfc86ceSHeiko Carstenssys_call_table_emu:
7184381f9f1SHendrik Brueckner#include "asm/syscall_table.h"
7194bfc86ceSHeiko Carstens#undef SYSCALL
7204bfc86ceSHeiko Carstens#endif
721