xref: /openbmc/linux/arch/s390/kernel/entry.S (revision 742aed05af97dc5ba6c53a4b6cb6a7b31e32f9e9)
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
323a890380SHeiko CarstensSTACK_SHIFT = PAGE_SHIFT + THREAD_SIZE_ORDER
334bfc86ceSHeiko CarstensSTACK_SIZE  = 1 << STACK_SHIFT
344bfc86ceSHeiko CarstensSTACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
354bfc86ceSHeiko Carstens
36e5b98199SMartin Schwidefsky_LPP_OFFSET	= __LC_LPP
37e5b98199SMartin Schwidefsky
383b051e89SSven Schnelle	.macro STBEAR address
39fad442d3SHeiko Carstens	ALTERNATIVE "nop", ".insn s,0xb2010000,\address", 193
403b051e89SSven Schnelle	.endm
413b051e89SSven Schnelle
423b051e89SSven Schnelle	.macro LBEAR address
43fad442d3SHeiko Carstens	ALTERNATIVE "nop", ".insn s,0xb2000000,\address", 193
443b051e89SSven Schnelle	.endm
453b051e89SSven Schnelle
463b051e89SSven Schnelle	.macro LPSWEY address,lpswe
47fad442d3SHeiko Carstens	ALTERNATIVE "b \lpswe; nopr", ".insn siy,0xeb0000000071,\address,0", 193
483b051e89SSven Schnelle	.endm
493b051e89SSven Schnelle
503b051e89SSven Schnelle	.macro MBEAR reg
51fad442d3SHeiko Carstens	ALTERNATIVE "brcl 0,0", __stringify(mvc __PT_LAST_BREAK(8,\reg),__LC_LAST_BREAK), 193
523b051e89SSven Schnelle	.endm
533b051e89SSven Schnelle
54ce3dc447SMartin Schwidefsky	.macro	CHECK_STACK savearea
554bfc86ceSHeiko Carstens#ifdef CONFIG_CHECK_STACK
56ce3dc447SMartin Schwidefsky	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
574bfc86ceSHeiko Carstens	lghi	%r14,\savearea
584bfc86ceSHeiko Carstens	jz	stack_overflow
594bfc86ceSHeiko Carstens#endif
604bfc86ceSHeiko Carstens	.endm
614bfc86ceSHeiko Carstens
62ce3dc447SMartin Schwidefsky	.macro	CHECK_VMAP_STACK savearea,oklabel
63ce3dc447SMartin Schwidefsky#ifdef CONFIG_VMAP_STACK
64ce3dc447SMartin Schwidefsky	lgr	%r14,%r15
65ce3dc447SMartin Schwidefsky	nill	%r14,0x10000 - STACK_SIZE
66ce3dc447SMartin Schwidefsky	oill	%r14,STACK_INIT
67ce3dc447SMartin Schwidefsky	clg	%r14,__LC_KERNEL_STACK
68ce3dc447SMartin Schwidefsky	je	\oklabel
69ce3dc447SMartin Schwidefsky	clg	%r14,__LC_ASYNC_STACK
70ce3dc447SMartin Schwidefsky	je	\oklabel
71b61b1595SSven Schnelle	clg	%r14,__LC_MCCK_STACK
72b61b1595SSven Schnelle	je	\oklabel
73ce3dc447SMartin Schwidefsky	clg	%r14,__LC_NODAT_STACK
74ce3dc447SMartin Schwidefsky	je	\oklabel
75ce3dc447SMartin Schwidefsky	clg	%r14,__LC_RESTART_STACK
76ce3dc447SMartin Schwidefsky	je	\oklabel
77ce3dc447SMartin Schwidefsky	lghi	%r14,\savearea
78ce3dc447SMartin Schwidefsky	j	stack_overflow
79ce3dc447SMartin Schwidefsky#else
80ce3dc447SMartin Schwidefsky	j	\oklabel
81ce3dc447SMartin Schwidefsky#endif
82ce3dc447SMartin Schwidefsky	.endm
83ce3dc447SMartin Schwidefsky
8483abeffbSHendrik Brueckner	/*
8583abeffbSHendrik Brueckner	 * The TSTMSK macro generates a test-under-mask instruction by
8683abeffbSHendrik Brueckner	 * calculating the memory offset for the specified mask value.
8783abeffbSHendrik Brueckner	 * Mask value can be any constant.  The macro shifts the mask
8883abeffbSHendrik Brueckner	 * value to calculate the memory offset for the test-under-mask
8983abeffbSHendrik Brueckner	 * instruction.
9083abeffbSHendrik Brueckner	 */
9183abeffbSHendrik Brueckner	.macro TSTMSK addr, mask, size=8, bytepos=0
9283abeffbSHendrik Brueckner		.if (\bytepos < \size) && (\mask >> 8)
9383abeffbSHendrik Brueckner			.if (\mask & 0xff)
9483abeffbSHendrik Brueckner				.error "Mask exceeds byte boundary"
9583abeffbSHendrik Brueckner			.endif
9683abeffbSHendrik Brueckner			TSTMSK \addr, "(\mask >> 8)", \size, "(\bytepos + 1)"
9783abeffbSHendrik Brueckner			.exitm
9883abeffbSHendrik Brueckner		.endif
9983abeffbSHendrik Brueckner		.ifeq \mask
10083abeffbSHendrik Brueckner			.error "Mask must not be zero"
10183abeffbSHendrik Brueckner		.endif
10283abeffbSHendrik Brueckner		off = \size - \bytepos - 1
10383abeffbSHendrik Brueckner		tm	off+\addr, \mask
10483abeffbSHendrik Brueckner	.endm
10583abeffbSHendrik Brueckner
106d768bd89SMartin Schwidefsky	.macro BPOFF
107fad442d3SHeiko Carstens	ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,12,0", 82
108d768bd89SMartin Schwidefsky	.endm
109d768bd89SMartin Schwidefsky
110d768bd89SMartin Schwidefsky	.macro BPON
111fad442d3SHeiko Carstens	ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,13,0", 82
112d768bd89SMartin Schwidefsky	.endm
113d768bd89SMartin Schwidefsky
1146b73044bSMartin Schwidefsky	.macro BPENTER tif_ptr,tif_mask
1156982dba1SHeiko Carstens	ALTERNATIVE "TSTMSK \tif_ptr,\tif_mask; jz .+8; .insn rrf,0xb2e80000,0,0,13,0", \
116fad442d3SHeiko Carstens		    "j .+12; nop; nop", 82
1176b73044bSMartin Schwidefsky	.endm
1186b73044bSMartin Schwidefsky
1196b73044bSMartin Schwidefsky	.macro BPEXIT tif_ptr,tif_mask
1206b73044bSMartin Schwidefsky	TSTMSK	\tif_ptr,\tif_mask
1216982dba1SHeiko Carstens	ALTERNATIVE "jz .+8;  .insn rrf,0xb2e80000,0,0,12,0", \
1226982dba1SHeiko Carstens		    "jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", 82
1236b73044bSMartin Schwidefsky	.endm
1246b73044bSMartin Schwidefsky
125b5415c8fSAlexander Gordeev#if IS_ENABLED(CONFIG_KVM)
126b5415c8fSAlexander Gordeev	/*
127b5415c8fSAlexander Gordeev	 * The OUTSIDE macro jumps to the provided label in case the value
128b5415c8fSAlexander Gordeev	 * in the provided register is outside of the provided range. The
129b5415c8fSAlexander Gordeev	 * macro is useful for checking whether a PSW stored in a register
130b5415c8fSAlexander Gordeev	 * pair points inside or outside of a block of instructions.
131b5415c8fSAlexander Gordeev	 * @reg: register to check
132b5415c8fSAlexander Gordeev	 * @start: start of the range
133b5415c8fSAlexander Gordeev	 * @end: end of the range
134b5415c8fSAlexander Gordeev	 * @outside_label: jump here if @reg is outside of [@start..@end)
135b5415c8fSAlexander Gordeev	 */
136b5415c8fSAlexander Gordeev	.macro OUTSIDE reg,start,end,outside_label
137b5415c8fSAlexander Gordeev	lgr	%r14,\reg
138b5415c8fSAlexander Gordeev	larl	%r13,\start
139b5415c8fSAlexander Gordeev	slgr	%r14,%r13
1404c25f0ffSHeiko Carstens#ifdef CONFIG_AS_IS_LLVM
1414c25f0ffSHeiko Carstens	clgfrl	%r14,.Lrange_size\@
1424c25f0ffSHeiko Carstens#else
1434c25f0ffSHeiko Carstens	clgfi	%r14,\end - \start
1444c25f0ffSHeiko Carstens#endif
145b5415c8fSAlexander Gordeev	jhe	\outside_label
1464c25f0ffSHeiko Carstens#ifdef CONFIG_AS_IS_LLVM
1474c25f0ffSHeiko Carstens	.section .rodata, "a"
1484c25f0ffSHeiko Carstens	.align 4
1494c25f0ffSHeiko Carstens.Lrange_size\@:
1504c25f0ffSHeiko Carstens	.long	\end - \start
1514c25f0ffSHeiko Carstens	.previous
1524c25f0ffSHeiko Carstens#endif
153b5415c8fSAlexander Gordeev	.endm
154fbbdfca5SAlexander Gordeev
155fbbdfca5SAlexander Gordeev	.macro SIEEXIT
156fbbdfca5SAlexander Gordeev	lg	%r9,__SF_SIE_CONTROL(%r15)	# get control block pointer
157fbbdfca5SAlexander Gordeev	ni	__SIE_PROG0C+3(%r9),0xfe	# no longer in SIE
158fbbdfca5SAlexander Gordeev	lctlg	%c1,%c1,__LC_KERNEL_ASCE	# load primary asce
159fbbdfca5SAlexander Gordeev	larl	%r9,sie_exit			# skip forward to sie_exit
160fbbdfca5SAlexander Gordeev	.endm
161b5415c8fSAlexander Gordeev#endif
162b5415c8fSAlexander Gordeev
1636dd85fbbSMartin Schwidefsky	GEN_BR_THUNK %r14
164f19fbd5eSMartin Schwidefsky
1654bfc86ceSHeiko Carstens	.section .kprobes.text, "ax"
16646210c44SHeiko Carstens.Ldummy:
16746210c44SHeiko Carstens	/*
16856e62a73SSven Schnelle	 * This nop exists only in order to avoid that __bpon starts at
16946210c44SHeiko Carstens	 * the beginning of the kprobes text section. In that case we would
17046210c44SHeiko Carstens	 * have several symbols at the same address. E.g. objdump would take
17146210c44SHeiko Carstens	 * an arbitrary symbol name when disassembling this code.
17256e62a73SSven Schnelle	 * With the added nop in between the __bpon symbol is unique
17346210c44SHeiko Carstens	 * again.
17446210c44SHeiko Carstens	 */
17546210c44SHeiko Carstens	nop	0
1764bfc86ceSHeiko Carstens
177d768bd89SMartin SchwidefskyENTRY(__bpon)
178d768bd89SMartin Schwidefsky	.globl __bpon
179d768bd89SMartin Schwidefsky	BPON
1806dd85fbbSMartin Schwidefsky	BR_EX	%r14
18126a374aeSMartin SchwidefskyENDPROC(__bpon)
182d768bd89SMartin Schwidefsky
1834bfc86ceSHeiko Carstens/*
1844bfc86ceSHeiko Carstens * Scheduler resume function, called by switch_to
1854bfc86ceSHeiko Carstens *  gpr2 = (task_struct *) prev
1864bfc86ceSHeiko Carstens *  gpr3 = (task_struct *) next
1874bfc86ceSHeiko Carstens * Returns:
1884bfc86ceSHeiko Carstens *  gpr2 = prev
1894bfc86ceSHeiko Carstens */
1904bfc86ceSHeiko CarstensENTRY(__switch_to)
1914bfc86ceSHeiko Carstens	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
1923241d3ebSHeiko Carstens	lghi	%r4,__TASK_stack
1933241d3ebSHeiko Carstens	lghi	%r1,__TASK_thread
1949fed920eSVasily Gorbik	llill	%r5,STACK_INIT
1953241d3ebSHeiko Carstens	stg	%r15,__THREAD_ksp(%r1,%r2)	# store kernel stack of prev
1969fed920eSVasily Gorbik	lg	%r15,0(%r4,%r3)			# start of kernel stack of next
1979fed920eSVasily Gorbik	agr	%r15,%r5			# end of kernel stack of next
1984bfc86ceSHeiko Carstens	stg	%r3,__LC_CURRENT		# store task struct of next
1994bfc86ceSHeiko Carstens	stg	%r15,__LC_KERNEL_STACK		# store end of kernel stack
2003241d3ebSHeiko Carstens	lg	%r15,__THREAD_ksp(%r1,%r3)	# load kernel stack of next
2013241d3ebSHeiko Carstens	aghi	%r3,__TASK_pid
2023241d3ebSHeiko Carstens	mvc	__LC_CURRENT_PID(4,%r0),0(%r3)	# store pid of next
2034bfc86ceSHeiko Carstens	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
204fad442d3SHeiko Carstens	ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40
2056dd85fbbSMartin Schwidefsky	BR_EX	%r14
20626a374aeSMartin SchwidefskyENDPROC(__switch_to)
2074bfc86ceSHeiko Carstens
208d0fc4107SMartin Schwidefsky#if IS_ENABLED(CONFIG_KVM)
209d0fc4107SMartin Schwidefsky/*
210d0fc4107SMartin Schwidefsky * sie64a calling convention:
211d0fc4107SMartin Schwidefsky * %r2 pointer to sie control block
212d0fc4107SMartin Schwidefsky * %r3 guest register save area
213d0fc4107SMartin Schwidefsky */
214d0fc4107SMartin SchwidefskyENTRY(sie64a)
215d0fc4107SMartin Schwidefsky	stmg	%r6,%r14,__SF_GPRS(%r15)	# save kernel registers
2166b73044bSMartin Schwidefsky	lg	%r12,__LC_CURRENT
21792fa7a13SMartin Schwidefsky	stg	%r2,__SF_SIE_CONTROL(%r15)	# save control block pointer
21892fa7a13SMartin Schwidefsky	stg	%r3,__SF_SIE_SAVEAREA(%r15)	# save guest register save area
21992fa7a13SMartin Schwidefsky	xc	__SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0
22092fa7a13SMartin Schwidefsky	mvc	__SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags
221d0fc4107SMartin Schwidefsky	lmg	%r0,%r13,0(%r3)			# load guest gprs 0-13
222d0fc4107SMartin Schwidefsky	lg	%r14,__LC_GMAP			# get gmap pointer
223d0fc4107SMartin Schwidefsky	ltgr	%r14,%r14
224d0fc4107SMartin Schwidefsky	jz	.Lsie_gmap
225d0fc4107SMartin Schwidefsky	lctlg	%c1,%c1,__GMAP_ASCE(%r14)	# load primary asce
226d0fc4107SMartin Schwidefsky.Lsie_gmap:
22792fa7a13SMartin Schwidefsky	lg	%r14,__SF_SIE_CONTROL(%r15)	# get control block pointer
228d0fc4107SMartin Schwidefsky	oi	__SIE_PROG0C+3(%r14),1		# we are going into SIE now
229d0fc4107SMartin Schwidefsky	tm	__SIE_PROG20+3(%r14),3		# last exit...
230d0fc4107SMartin Schwidefsky	jnz	.Lsie_skip
23183abeffbSHendrik Brueckner	TSTMSK	__LC_CPU_FLAGS,_CIF_FPU
232d0fc4107SMartin Schwidefsky	jo	.Lsie_skip			# exit if fp/vx regs changed
23392fa7a13SMartin Schwidefsky	BPEXIT	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
234c929500dSQingFeng Hao.Lsie_entry:
235d0fc4107SMartin Schwidefsky	sie	0(%r14)
23629ccaa4bSAlexander Gordeev# Let the next instruction be NOP to avoid triggering a machine check
23729ccaa4bSAlexander Gordeev# and handling it in a guest as result of the instruction execution.
23829ccaa4bSAlexander Gordeev	nopr	7
23929ccaa4bSAlexander Gordeev.Lsie_leave:
240d768bd89SMartin Schwidefsky	BPOFF
24192fa7a13SMartin Schwidefsky	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
242d0fc4107SMartin Schwidefsky.Lsie_skip:
243d0fc4107SMartin Schwidefsky	ni	__SIE_PROG0C+3(%r14),0xfe	# no longer in SIE
24487d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE	# load primary asce
245d0fc4107SMartin Schwidefsky.Lsie_done:
246d0fc4107SMartin Schwidefsky# some program checks are suppressing. C code (e.g. do_protection_exception)
247c0e7bb38SChristian Borntraeger# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
248c0e7bb38SChristian Borntraeger# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
249c0e7bb38SChristian Borntraeger# Other instructions between sie64a and .Lsie_done should not cause program
250c0e7bb38SChristian Borntraeger# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
251c0e7bb38SChristian Borntraeger.Lrewind_pad6:
252c0e7bb38SChristian Borntraeger	nopr	7
253c0e7bb38SChristian Borntraeger.Lrewind_pad4:
254c0e7bb38SChristian Borntraeger	nopr	7
255c0e7bb38SChristian Borntraeger.Lrewind_pad2:
256c0e7bb38SChristian Borntraeger	nopr	7
257d0fc4107SMartin Schwidefsky	.globl sie_exit
258d0fc4107SMartin Schwidefskysie_exit:
25992fa7a13SMartin Schwidefsky	lg	%r14,__SF_SIE_SAVEAREA(%r15)	# load guest register save area
260d0fc4107SMartin Schwidefsky	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
2617041d281SMartin Schwidefsky	xgr	%r0,%r0				# clear guest registers to
2627041d281SMartin Schwidefsky	xgr	%r1,%r1				# prevent speculative use
2637041d281SMartin Schwidefsky	xgr	%r3,%r3
2647041d281SMartin Schwidefsky	xgr	%r4,%r4
2657041d281SMartin Schwidefsky	xgr	%r5,%r5
266d0fc4107SMartin Schwidefsky	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
26792fa7a13SMartin Schwidefsky	lg	%r2,__SF_SIE_REASON(%r15)	# return exit reason code
2686dd85fbbSMartin Schwidefsky	BR_EX	%r14
269d0fc4107SMartin Schwidefsky.Lsie_fault:
270d0fc4107SMartin Schwidefsky	lghi	%r14,-EFAULT
27192fa7a13SMartin Schwidefsky	stg	%r14,__SF_SIE_REASON(%r15)	# set exit reason code
272d0fc4107SMartin Schwidefsky	j	sie_exit
273d0fc4107SMartin Schwidefsky
274c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad6,.Lsie_fault)
275c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad4,.Lsie_fault)
276c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad2,.Lsie_fault)
277d0fc4107SMartin Schwidefsky	EX_TABLE(sie_exit,.Lsie_fault)
27826a374aeSMartin SchwidefskyENDPROC(sie64a)
279711f5df7SAl ViroEXPORT_SYMBOL(sie64a)
280711f5df7SAl ViroEXPORT_SYMBOL(sie_exit)
281d0fc4107SMartin Schwidefsky#endif
282d0fc4107SMartin Schwidefsky
2834bfc86ceSHeiko Carstens/*
2844bfc86ceSHeiko Carstens * SVC interrupt handler routine. System calls are synchronous events and
2857b7735c5SChristian Borntraeger * are entered with interrupts disabled.
2864bfc86ceSHeiko Carstens */
2874bfc86ceSHeiko Carstens
2884bfc86ceSHeiko CarstensENTRY(system_call)
28956e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
2904bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
291d768bd89SMartin Schwidefsky	BPOFF
29256e62a73SSven Schnelle	lghi	%r14,0
2934bfc86ceSHeiko Carstens.Lsysc_per:
2943b051e89SSven Schnelle	STBEAR	__LC_LAST_BREAK
29587d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
29656e62a73SSven Schnelle	lg	%r12,__LC_CURRENT
2974bfc86ceSHeiko Carstens	lg	%r15,__LC_KERNEL_STACK
2989365965dSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
29956e62a73SSven Schnelle	stmg	%r0,%r7,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
30056e62a73SSven Schnelle	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
301d3f46896SChristian Borntraeger	# clear user controlled register to prevent speculative use
302d3f46896SChristian Borntraeger	xgr	%r0,%r0
30356e62a73SSven Schnelle	xgr	%r1,%r1
30456e62a73SSven Schnelle	xgr	%r4,%r4
30556e62a73SSven Schnelle	xgr	%r5,%r5
30656e62a73SSven Schnelle	xgr	%r6,%r6
30756e62a73SSven Schnelle	xgr	%r7,%r7
30856e62a73SSven Schnelle	xgr	%r8,%r8
30956e62a73SSven Schnelle	xgr	%r9,%r9
31056e62a73SSven Schnelle	xgr	%r10,%r10
31156e62a73SSven Schnelle	xgr	%r11,%r11
31256e62a73SSven Schnelle	la	%r2,STACK_FRAME_OVERHEAD(%r15)	# pointer to pt_regs
313af9ad822SSven Schnelle	mvc	__PT_R8(64,%r2),__LC_SAVE_AREA_SYNC
3143b051e89SSven Schnelle	MBEAR	%r2
31556e62a73SSven Schnelle	lgr	%r3,%r14
31656e62a73SSven Schnelle	brasl	%r14,__do_syscall
31787d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_USER_ASCE
31856e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
3196b73044bSMartin Schwidefsky	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3203b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
32156e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
3224bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
3233b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
32426a374aeSMartin SchwidefskyENDPROC(system_call)
3254bfc86ceSHeiko Carstens
3264bfc86ceSHeiko Carstens#
3274bfc86ceSHeiko Carstens# a new process exits the kernel with ret_from_fork
3284bfc86ceSHeiko Carstens#
3294bfc86ceSHeiko CarstensENTRY(ret_from_fork)
33056e62a73SSven Schnelle	lgr	%r3,%r11
33156e62a73SSven Schnelle	brasl	%r14,__ret_from_fork
33256e62a73SSven Schnelle	lctlg	%c1,%c1,__LC_USER_ASCE
33356e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
33456e62a73SSven Schnelle	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3353b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
33656e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
33756e62a73SSven Schnelle	stpt	__LC_EXIT_TIMER
3383b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
33926a374aeSMartin SchwidefskyENDPROC(ret_from_fork)
34026a374aeSMartin Schwidefsky
3414bfc86ceSHeiko Carstens/*
3424bfc86ceSHeiko Carstens * Program check handler routine
3434bfc86ceSHeiko Carstens */
3444bfc86ceSHeiko Carstens
3454bfc86ceSHeiko CarstensENTRY(pgm_check_handler)
34656e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
347d768bd89SMartin Schwidefsky	BPOFF
3484bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
34956e62a73SSven Schnelle	lg	%r12,__LC_CURRENT
35056e62a73SSven Schnelle	lghi	%r10,0
3514bfc86ceSHeiko Carstens	lmg	%r8,%r9,__LC_PGM_OLD_PSW
35287d59863SHeiko Carstens	tmhh	%r8,0x0001		# coming from user space?
35387d59863SHeiko Carstens	jno	.Lpgm_skip_asce
35487d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
35556e62a73SSven Schnelle	j	3f			# -> fault in user space
35687d59863SHeiko Carstens.Lpgm_skip_asce:
357d0fc4107SMartin Schwidefsky#if IS_ENABLED(CONFIG_KVM)
3580a5e2ec2SMartin Schwidefsky	# cleanup critical section for program checks in sie64a
359b5415c8fSAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,1f
360fbbdfca5SAlexander Gordeev	SIEEXIT
36156e62a73SSven Schnelle	lghi	%r10,_PIF_GUEST_FAULT
362d0fc4107SMartin Schwidefsky#endif
3630b38b5e1SSven Schnelle1:	tmhh	%r8,0x4000		# PER bit set in old PSW ?
3640b38b5e1SSven Schnelle	jnz	2f			# -> enabled, can't be a double fault
3654bfc86ceSHeiko Carstens	tm	__LC_PGM_ILC+3,0x80	# check for per exception
3664bfc86ceSHeiko Carstens	jnz	.Lpgm_svcper		# -> single stepped svc
3670b38b5e1SSven Schnelle2:	CHECK_STACK __LC_SAVE_AREA_SYNC
3684bfc86ceSHeiko Carstens	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
36956e62a73SSven Schnelle	# CHECK_VMAP_STACK branches to stack_overflow or 4f
37056e62a73SSven Schnelle	CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f
37156e62a73SSven Schnelle3:	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
3724bfc86ceSHeiko Carstens	lg	%r15,__LC_KERNEL_STACK
37356e62a73SSven Schnelle4:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
37456e62a73SSven Schnelle	stg	%r10,__PT_FLAGS(%r11)
37556e62a73SSven Schnelle	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
3764bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
37756e62a73SSven Schnelle	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
3783b051e89SSven Schnelle	mvc	__PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
37956e62a73SSven Schnelle	stmg	%r8,%r9,__PT_PSW(%r11)
38056e62a73SSven Schnelle
3817041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
3827041d281SMartin Schwidefsky	xgr	%r0,%r0
3837041d281SMartin Schwidefsky	xgr	%r1,%r1
3847041d281SMartin Schwidefsky	xgr	%r3,%r3
3857041d281SMartin Schwidefsky	xgr	%r4,%r4
3867041d281SMartin Schwidefsky	xgr	%r5,%r5
3877041d281SMartin Schwidefsky	xgr	%r6,%r6
3887041d281SMartin Schwidefsky	xgr	%r7,%r7
38956e62a73SSven Schnelle	lgr	%r2,%r11
39056e62a73SSven Schnelle	brasl	%r14,__do_pgm_check
39156e62a73SSven Schnelle	tmhh	%r8,0x0001		# returning to user space?
39256e62a73SSven Schnelle	jno	.Lpgm_exit_kernel
39356e62a73SSven Schnelle	lctlg	%c1,%c1,__LC_USER_ASCE
39456e62a73SSven Schnelle	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3950cd9b723SHeiko Carstens	stpt	__LC_EXIT_TIMER
39656e62a73SSven Schnelle.Lpgm_exit_kernel:
39756e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
3983b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
39956e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
4003b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
4014bfc86ceSHeiko Carstens
4024bfc86ceSHeiko Carstens#
4034bfc86ceSHeiko Carstens# single stepped system call
4044bfc86ceSHeiko Carstens#
4054bfc86ceSHeiko Carstens.Lpgm_svcper:
4064bfc86ceSHeiko Carstens	mvc	__LC_RETURN_PSW(8),__LC_SVC_NEW_PSW
4074bfc86ceSHeiko Carstens	larl	%r14,.Lsysc_per
4084bfc86ceSHeiko Carstens	stg	%r14,__LC_RETURN_PSW+8
40956e62a73SSven Schnelle	lghi	%r14,1
4103b051e89SSven Schnelle	LBEAR	__LC_PGM_LAST_BREAK
4113b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE # branch to .Lsysc_per
41226a374aeSMartin SchwidefskyENDPROC(pgm_check_handler)
4134bfc86ceSHeiko Carstens
4144bfc86ceSHeiko Carstens/*
41556e62a73SSven Schnelle * Interrupt handler macro used for external and IO interrupts.
4164bfc86ceSHeiko Carstens */
41756e62a73SSven Schnelle.macro INT_HANDLER name,lc_old_psw,handler
41856e62a73SSven SchnelleENTRY(\name)
41910bc15baSVasily Gorbik	stckf	__LC_INT_CLOCK
42056e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
4213b051e89SSven Schnelle	STBEAR	__LC_LAST_BREAK
422d768bd89SMartin Schwidefsky	BPOFF
4234bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
424d5c352cdSHeiko Carstens	lg	%r12,__LC_CURRENT
42556e62a73SSven Schnelle	lmg	%r8,%r9,\lc_old_psw
426b0d31159SSven Schnelle	tmhh	%r8,0x0001			# interrupting from user ?
427b0d31159SSven Schnelle	jnz	1f
428b0d31159SSven Schnelle#if IS_ENABLED(CONFIG_KVM)
429b5415c8fSAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,0f
430fbbdfca5SAlexander Gordeev	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
431fbbdfca5SAlexander Gordeev	SIEEXIT
432b0d31159SSven Schnelle#endif
433b0d31159SSven Schnelle0:	CHECK_STACK __LC_SAVE_AREA_ASYNC
434b0d31159SSven Schnelle	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
435b0d31159SSven Schnelle	j	2f
436b0d31159SSven Schnelle1:	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
437b0d31159SSven Schnelle	lctlg	%c1,%c1,__LC_KERNEL_ASCE
438b0d31159SSven Schnelle	lg	%r15,__LC_KERNEL_STACK
439b74e409eSVasily Gorbik2:	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
440b74e409eSVasily Gorbik	la	%r11,STACK_FRAME_OVERHEAD(%r15)
4414bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
4427041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
4437041d281SMartin Schwidefsky	xgr	%r0,%r0
4447041d281SMartin Schwidefsky	xgr	%r1,%r1
4457041d281SMartin Schwidefsky	xgr	%r3,%r3
4467041d281SMartin Schwidefsky	xgr	%r4,%r4
4477041d281SMartin Schwidefsky	xgr	%r5,%r5
4487041d281SMartin Schwidefsky	xgr	%r6,%r6
4497041d281SMartin Schwidefsky	xgr	%r7,%r7
4507041d281SMartin Schwidefsky	xgr	%r10,%r10
451ca1f4d70SSven Schnelle	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
4524bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
4533b051e89SSven Schnelle	MBEAR	%r11
4544bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
45529b06ad7SHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
45656e62a73SSven Schnelle	brasl	%r14,\handler
4574bfc86ceSHeiko Carstens	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r11)
45856e62a73SSven Schnelle	tmhh	%r8,0x0001		# returning to user ?
45956e62a73SSven Schnelle	jno	2f
46087d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_USER_ASCE
4616b73044bSMartin Schwidefsky	BPEXIT	__TI_flags(%r12),_TIF_ISOLATE_BP
4624bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
4633b051e89SSven Schnelle2:	LBEAR	__PT_LAST_BREAK(%r11)
4643b051e89SSven Schnelle	lmg	%r0,%r15,__PT_R0(%r11)
4653b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
46656e62a73SSven SchnelleENDPROC(\name)
46756e62a73SSven Schnelle.endm
4684bfc86ceSHeiko Carstens
46956e62a73SSven SchnelleINT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
47056e62a73SSven SchnelleINT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
4714bfc86ceSHeiko Carstens
4724bfc86ceSHeiko Carstens/*
4730b0ed657SSven Schnelle * Load idle PSW.
4744bfc86ceSHeiko Carstens */
4754bfc86ceSHeiko CarstensENTRY(psw_idle)
476a994eddbSVasily Gorbik	stg	%r14,(__SF_GPRS+8*8)(%r15)
4774bfc86ceSHeiko Carstens	stg	%r3,__SF_EMPTY(%r15)
47856e62a73SSven Schnelle	larl	%r1,psw_idle_exit
4794bfc86ceSHeiko Carstens	stg	%r1,__SF_EMPTY+8(%r15)
48072d38b19SMartin Schwidefsky	larl	%r1,smp_cpu_mtid
48172d38b19SMartin Schwidefsky	llgf	%r1,0(%r1)
48272d38b19SMartin Schwidefsky	ltgr	%r1,%r1
48372d38b19SMartin Schwidefsky	jz	.Lpsw_idle_stcctm
48456e62a73SSven Schnelle	.insn	rsy,0xeb0000000017,%r1,5,__MT_CYCLES_ENTER(%r2)
48572d38b19SMartin Schwidefsky.Lpsw_idle_stcctm:
486419123f9SMartin Schwidefsky	oi	__LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT
487d768bd89SMartin Schwidefsky	BPON
48810bc15baSVasily Gorbik	stckf	__CLOCK_IDLE_ENTER(%r2)
4894bfc86ceSHeiko Carstens	stpt	__TIMER_IDLE_ENTER(%r2)
4904bfc86ceSHeiko Carstens	lpswe	__SF_EMPTY(%r15)
49156e62a73SSven Schnelle.globl psw_idle_exit
49256e62a73SSven Schnellepsw_idle_exit:
4936dd85fbbSMartin Schwidefsky	BR_EX	%r14
49426a374aeSMartin SchwidefskyENDPROC(psw_idle)
4954bfc86ceSHeiko Carstens
496b5510d9bSHendrik Brueckner/*
4974bfc86ceSHeiko Carstens * Machine check handler routines
4984bfc86ceSHeiko Carstens */
4994bfc86ceSHeiko CarstensENTRY(mcck_int_handler)
50010bc15baSVasily Gorbik	stckf	__LC_MCCK_CLOCK
501d768bd89SMartin Schwidefsky	BPOFF
5023037a52fSMartin Schwidefsky	la	%r1,4095		# validate r1
5033037a52fSMartin Schwidefsky	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# validate cpu timer
5043b051e89SSven Schnelle	LBEAR	__LC_LAST_BREAK_SAVE_AREA-4095(%r1)		# validate bear
5053037a52fSMartin Schwidefsky	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# validate gprs
506d5c352cdSHeiko Carstens	lg	%r12,__LC_CURRENT
5074bfc86ceSHeiko Carstens	lmg	%r8,%r9,__LC_MCK_OLD_PSW
50883abeffbSHendrik Brueckner	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE
5094bfc86ceSHeiko Carstens	jo	.Lmcck_panic		# yes -> rest of mcck code invalid
5103037a52fSMartin Schwidefsky	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_CR_VALID
5113037a52fSMartin Schwidefsky	jno	.Lmcck_panic		# control registers invalid -> panic
5123037a52fSMartin Schwidefsky	la	%r14,4095
5133037a52fSMartin Schwidefsky	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r14) # validate ctl regs
5143037a52fSMartin Schwidefsky	ptlb
5155fa2ea07SAlexander Gordeev	lghi	%r14,__LC_CPU_TIMER_SAVE_AREA
5164bfc86ceSHeiko Carstens	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
51783abeffbSHendrik Brueckner	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID
5184bfc86ceSHeiko Carstens	jo	3f
51956e62a73SSven Schnelle	la	%r14,__LC_SYS_ENTER_TIMER
52056e62a73SSven Schnelle	clc	0(8,%r14),__LC_EXIT_TIMER
5214bfc86ceSHeiko Carstens	jl	1f
5224bfc86ceSHeiko Carstens	la	%r14,__LC_EXIT_TIMER
5234bfc86ceSHeiko Carstens1:	clc	0(8,%r14),__LC_LAST_UPDATE_TIMER
5244bfc86ceSHeiko Carstens	jl	2f
5254bfc86ceSHeiko Carstens	la	%r14,__LC_LAST_UPDATE_TIMER
5264bfc86ceSHeiko Carstens2:	spt	0(%r14)
5274bfc86ceSHeiko Carstens	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
5283037a52fSMartin Schwidefsky3:	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_PSW_MWP_VALID
5293037a52fSMartin Schwidefsky	jno	.Lmcck_panic
5303037a52fSMartin Schwidefsky	tmhh	%r8,0x0001		# interrupting from user ?
531*742aed05SHeiko Carstens	jnz	.Lmcck_user
5323037a52fSMartin Schwidefsky	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID
5333037a52fSMartin Schwidefsky	jno	.Lmcck_panic
534b0d31159SSven Schnelle#if IS_ENABLED(CONFIG_KVM)
535*742aed05SHeiko Carstens	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,.Lmcck_stack
53629ccaa4bSAlexander Gordeev	OUTSIDE	%r9,.Lsie_entry,.Lsie_leave,4f
53720232b18SAlexander Gordeev	oi	__LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
538*742aed05SHeiko Carstens4:	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
539fbbdfca5SAlexander Gordeev	SIEEXIT
540b61b1595SSven Schnelle	j	.Lmcck_stack
541e2c13d64SAlexander Gordeev#endif
542*742aed05SHeiko Carstens.Lmcck_user:
543b0d31159SSven Schnelle	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
544b61b1595SSven Schnelle.Lmcck_stack:
545b61b1595SSven Schnelle	lg	%r15,__LC_MCCK_STACK
546b61b1595SSven Schnelle	la	%r11,STACK_FRAME_OVERHEAD(%r15)
54726521412SSven Schnelle	stctg	%c1,%c1,__PT_CR1(%r11)
548b61b1595SSven Schnelle	lctlg	%c1,%c1,__LC_KERNEL_ASCE
549b61b1595SSven Schnelle	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
5504bfc86ceSHeiko Carstens	lghi	%r14,__LC_GPREGS_SAVE_AREA+64
5514bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
5527041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
5537041d281SMartin Schwidefsky	xgr	%r0,%r0
5547041d281SMartin Schwidefsky	xgr	%r1,%r1
5557041d281SMartin Schwidefsky	xgr	%r3,%r3
5567041d281SMartin Schwidefsky	xgr	%r4,%r4
5577041d281SMartin Schwidefsky	xgr	%r5,%r5
5587041d281SMartin Schwidefsky	xgr	%r6,%r6
5597041d281SMartin Schwidefsky	xgr	%r7,%r7
5607041d281SMartin Schwidefsky	xgr	%r10,%r10
5614bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),0(%r14)
5624bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
5634bfc86ceSHeiko Carstens	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
5644bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
5654bfc86ceSHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
5664bfc86ceSHeiko Carstens	brasl	%r14,s390_do_machine_check
5670b0ed657SSven Schnelle	cghi	%r2,0
5680b0ed657SSven Schnelle	je	.Lmcck_return
5694bfc86ceSHeiko Carstens	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
5704bfc86ceSHeiko Carstens	mvc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
5714bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
5724bfc86ceSHeiko Carstens	la	%r11,STACK_FRAME_OVERHEAD(%r1)
57339d62336SThomas Richter	lgr	%r2,%r11
5744bfc86ceSHeiko Carstens	lgr	%r15,%r1
5754bfc86ceSHeiko Carstens	brasl	%r14,s390_handle_mcck
5764bfc86ceSHeiko Carstens.Lmcck_return:
57787d59863SHeiko Carstens	lctlg	%c1,%c1,__PT_CR1(%r11)
5784bfc86ceSHeiko Carstens	lmg	%r0,%r10,__PT_R0(%r11)
5794bfc86ceSHeiko Carstens	mvc	__LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
5804bfc86ceSHeiko Carstens	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
5814bfc86ceSHeiko Carstens	jno	0f
5826b73044bSMartin Schwidefsky	BPEXIT	__TI_flags(%r12),_TIF_ISOLATE_BP
5834bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
584fad442d3SHeiko Carstens0:	ALTERNATIVE "nop", __stringify(lghi %r12,__LC_LAST_BREAK_SAVE_AREA),193
5853b051e89SSven Schnelle	LBEAR	0(%r12)
5863b051e89SSven Schnelle	lmg	%r11,%r15,__PT_R11(%r11)
5873b051e89SSven Schnelle	LPSWEY	__LC_RETURN_MCCK_PSW,__LC_RETURN_MCCK_LPSWE
5884bfc86ceSHeiko Carstens
5894bfc86ceSHeiko Carstens.Lmcck_panic:
5907f6dc8d4SAlexander Gordeev	/*
5917f6dc8d4SAlexander Gordeev	 * Iterate over all possible CPU addresses in the range 0..0xffff
5927f6dc8d4SAlexander Gordeev	 * and stop each CPU using signal processor. Use compare and swap
5937f6dc8d4SAlexander Gordeev	 * to allow just one CPU-stopper and prevent concurrent CPUs from
5947f6dc8d4SAlexander Gordeev	 * stopping each other while leaving the others running.
5957f6dc8d4SAlexander Gordeev	 */
5967f6dc8d4SAlexander Gordeev	lhi	%r5,0
5977f6dc8d4SAlexander Gordeev	lhi	%r6,1
5987f6dc8d4SAlexander Gordeev	larl	%r7,.Lstop_lock
5997f6dc8d4SAlexander Gordeev	cs	%r5,%r6,0(%r7)		# single CPU-stopper only
6007f6dc8d4SAlexander Gordeev	jnz	4f
6017f6dc8d4SAlexander Gordeev	larl	%r7,.Lthis_cpu
6027f6dc8d4SAlexander Gordeev	stap	0(%r7)			# this CPU address
6037f6dc8d4SAlexander Gordeev	lh	%r4,0(%r7)
6047f6dc8d4SAlexander Gordeev	nilh	%r4,0
6057f6dc8d4SAlexander Gordeev	lhi	%r0,1
6067f6dc8d4SAlexander Gordeev	sll	%r0,16			# CPU counter
6077f6dc8d4SAlexander Gordeev	lhi	%r3,0			# next CPU address
6087f6dc8d4SAlexander Gordeev0:	cr	%r3,%r4
6097f6dc8d4SAlexander Gordeev	je	2f
6107f6dc8d4SAlexander Gordeev1:	sigp	%r1,%r3,SIGP_STOP	# stop next CPU
6117f6dc8d4SAlexander Gordeev	brc	SIGP_CC_BUSY,1b
6127f6dc8d4SAlexander Gordeev2:	ahi	%r3,1
6137f6dc8d4SAlexander Gordeev	brct	%r0,0b
6147f6dc8d4SAlexander Gordeev3:	sigp	%r1,%r4,SIGP_STOP	# stop this CPU
6157f6dc8d4SAlexander Gordeev	brc	SIGP_CC_BUSY,3b
6167f6dc8d4SAlexander Gordeev4:	j	4b
61726a374aeSMartin SchwidefskyENDPROC(mcck_int_handler)
6184bfc86ceSHeiko Carstens
6194bfc86ceSHeiko CarstensENTRY(restart_int_handler)
620fad442d3SHeiko Carstens	ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40
621e5b98199SMartin Schwidefsky	stg	%r15,__LC_SAVE_AREA_RESTART
622915fea04SAlexander Gordeev	TSTMSK	__LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4
623915fea04SAlexander Gordeev	jz	0f
624915fea04SAlexander Gordeev	la	%r15,4095
625915fea04SAlexander Gordeev	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r15)
626915fea04SAlexander Gordeev0:	larl	%r15,.Lstosm_tmp
627915fea04SAlexander Gordeev	stosm	0(%r15),0x04			# turn dat on, keep irqs off
6284bfc86ceSHeiko Carstens	lg	%r15,__LC_RESTART_STACK
629ce3dc447SMartin Schwidefsky	xc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15)
630ce3dc447SMartin Schwidefsky	stmg	%r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
631ce3dc447SMartin Schwidefsky	mvc	STACK_FRAME_OVERHEAD+__PT_R15(8,%r15),__LC_SAVE_AREA_RESTART
632ce3dc447SMartin Schwidefsky	mvc	STACK_FRAME_OVERHEAD+__PT_PSW(16,%r15),__LC_RST_OLD_PSW
6334bfc86ceSHeiko Carstens	xc	0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
6344bfc86ceSHeiko Carstens	lg	%r1,__LC_RESTART_FN		# load fn, parm & source cpu
6354bfc86ceSHeiko Carstens	lg	%r2,__LC_RESTART_DATA
636915fea04SAlexander Gordeev	lgf	%r3,__LC_RESTART_SOURCE
6374bfc86ceSHeiko Carstens	ltgr	%r3,%r3				# test source cpu address
6384bfc86ceSHeiko Carstens	jm	1f				# negative -> skip source stop
6394bfc86ceSHeiko Carstens0:	sigp	%r4,%r3,SIGP_SENSE		# sigp sense to source cpu
6404bfc86ceSHeiko Carstens	brc	10,0b				# wait for status stored
6414bfc86ceSHeiko Carstens1:	basr	%r14,%r1			# call function
6424bfc86ceSHeiko Carstens	stap	__SF_EMPTY(%r15)		# store cpu address
6434bfc86ceSHeiko Carstens	llgh	%r3,__SF_EMPTY(%r15)
6444bfc86ceSHeiko Carstens2:	sigp	%r4,%r3,SIGP_STOP		# sigp stop to current cpu
6454bfc86ceSHeiko Carstens	brc	2,2b
6464bfc86ceSHeiko Carstens3:	j	3b
64726a374aeSMartin SchwidefskyENDPROC(restart_int_handler)
6484bfc86ceSHeiko Carstens
6494bfc86ceSHeiko Carstens	.section .kprobes.text, "ax"
6504bfc86ceSHeiko Carstens
651ce3dc447SMartin Schwidefsky#if defined(CONFIG_CHECK_STACK) || defined(CONFIG_VMAP_STACK)
6524bfc86ceSHeiko Carstens/*
6534bfc86ceSHeiko Carstens * The synchronous or the asynchronous stack overflowed. We are dead.
6544bfc86ceSHeiko Carstens * No need to properly save the registers, we are going to panic anyway.
6554bfc86ceSHeiko Carstens * Setup a pt_regs so that show_trace can provide a good call trace.
6564bfc86ceSHeiko Carstens */
65726a374aeSMartin SchwidefskyENTRY(stack_overflow)
658ce3dc447SMartin Schwidefsky	lg	%r15,__LC_NODAT_STACK	# change to panic stack
6594bfc86ceSHeiko Carstens	la	%r11,STACK_FRAME_OVERHEAD(%r15)
6604bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
6614bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
6624bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),0(%r14)
6634bfc86ceSHeiko Carstens	stg	%r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
6644bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
6654bfc86ceSHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
6664bfc86ceSHeiko Carstens	jg	kernel_stack_overflow
66726a374aeSMartin SchwidefskyENDPROC(stack_overflow)
6684bfc86ceSHeiko Carstens#endif
6694bfc86ceSHeiko Carstens
6707f6dc8d4SAlexander Gordeev	.section .data, "aw"
6717f6dc8d4SAlexander Gordeev		.align	4
6727f6dc8d4SAlexander Gordeev.Lstop_lock:	.long	0
6737f6dc8d4SAlexander Gordeev.Lthis_cpu:	.short	0
674d35925b3SAlexander Gordeev.Lstosm_tmp:	.byte	0
6754bfc86ceSHeiko Carstens	.section .rodata, "a"
676ff4a742dSGerald Schaefer#define SYSCALL(esame,emu)	.quad __s390x_ ## esame
6774bfc86ceSHeiko Carstens	.globl	sys_call_table
6784bfc86ceSHeiko Carstenssys_call_table:
6794381f9f1SHendrik Brueckner#include "asm/syscall_table.h"
6804bfc86ceSHeiko Carstens#undef SYSCALL
6814bfc86ceSHeiko Carstens
6824bfc86ceSHeiko Carstens#ifdef CONFIG_COMPAT
6834bfc86ceSHeiko Carstens
684ff4a742dSGerald Schaefer#define SYSCALL(esame,emu)	.quad __s390_ ## emu
6854bfc86ceSHeiko Carstens	.globl	sys_call_table_emu
6864bfc86ceSHeiko Carstenssys_call_table_emu:
6874381f9f1SHendrik Brueckner#include "asm/syscall_table.h"
6884bfc86ceSHeiko Carstens#undef SYSCALL
6894bfc86ceSHeiko Carstens#endif
690