xref: /openbmc/linux/arch/s390/kernel/entry.S (revision 6b33e68ab30949f9657e2acc59766977ae63e1cc)
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
125d35925b3SAlexander Gordeev	/*
126d35925b3SAlexander Gordeev	 * The CHKSTG macro jumps to the provided label in case the
127d35925b3SAlexander Gordeev	 * machine check interruption code reports one of unrecoverable
128d35925b3SAlexander Gordeev	 * storage errors:
129d35925b3SAlexander Gordeev	 * - Storage error uncorrected
130d35925b3SAlexander Gordeev	 * - Storage key error uncorrected
131d35925b3SAlexander Gordeev	 * - Storage degradation with Failing-storage-address validity
132d35925b3SAlexander Gordeev	 */
133d35925b3SAlexander Gordeev	.macro CHKSTG errlabel
134d35925b3SAlexander Gordeev	TSTMSK	__LC_MCCK_CODE,(MCCK_CODE_STG_ERROR|MCCK_CODE_STG_KEY_ERROR)
135d35925b3SAlexander Gordeev	jnz	\errlabel
136d35925b3SAlexander Gordeev	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_STG_DEGRAD
13715256194SHeiko Carstens	jz	.Loklabel\@
138d35925b3SAlexander Gordeev	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_STG_FAIL_ADDR
139d35925b3SAlexander Gordeev	jnz	\errlabel
14015256194SHeiko Carstens.Loklabel\@:
141d35925b3SAlexander Gordeev	.endm
142d35925b3SAlexander Gordeev
143b5415c8fSAlexander Gordeev#if IS_ENABLED(CONFIG_KVM)
144b5415c8fSAlexander Gordeev	/*
145b5415c8fSAlexander Gordeev	 * The OUTSIDE macro jumps to the provided label in case the value
146b5415c8fSAlexander Gordeev	 * in the provided register is outside of the provided range. The
147b5415c8fSAlexander Gordeev	 * macro is useful for checking whether a PSW stored in a register
148b5415c8fSAlexander Gordeev	 * pair points inside or outside of a block of instructions.
149b5415c8fSAlexander Gordeev	 * @reg: register to check
150b5415c8fSAlexander Gordeev	 * @start: start of the range
151b5415c8fSAlexander Gordeev	 * @end: end of the range
152b5415c8fSAlexander Gordeev	 * @outside_label: jump here if @reg is outside of [@start..@end)
153b5415c8fSAlexander Gordeev	 */
154b5415c8fSAlexander Gordeev	.macro OUTSIDE reg,start,end,outside_label
155b5415c8fSAlexander Gordeev	lgr	%r14,\reg
156b5415c8fSAlexander Gordeev	larl	%r13,\start
157b5415c8fSAlexander Gordeev	slgr	%r14,%r13
1584c25f0ffSHeiko Carstens#ifdef CONFIG_AS_IS_LLVM
1594c25f0ffSHeiko Carstens	clgfrl	%r14,.Lrange_size\@
1604c25f0ffSHeiko Carstens#else
1614c25f0ffSHeiko Carstens	clgfi	%r14,\end - \start
1624c25f0ffSHeiko Carstens#endif
163b5415c8fSAlexander Gordeev	jhe	\outside_label
1644c25f0ffSHeiko Carstens#ifdef CONFIG_AS_IS_LLVM
1654c25f0ffSHeiko Carstens	.section .rodata, "a"
1664c25f0ffSHeiko Carstens	.align 4
1674c25f0ffSHeiko Carstens.Lrange_size\@:
1684c25f0ffSHeiko Carstens	.long	\end - \start
1694c25f0ffSHeiko Carstens	.previous
1704c25f0ffSHeiko Carstens#endif
171b5415c8fSAlexander Gordeev	.endm
172fbbdfca5SAlexander Gordeev
173fbbdfca5SAlexander Gordeev	.macro SIEEXIT
174fbbdfca5SAlexander Gordeev	lg	%r9,__SF_SIE_CONTROL(%r15)	# get control block pointer
175fbbdfca5SAlexander Gordeev	ni	__SIE_PROG0C+3(%r9),0xfe	# no longer in SIE
176fbbdfca5SAlexander Gordeev	lctlg	%c1,%c1,__LC_KERNEL_ASCE	# load primary asce
177fbbdfca5SAlexander Gordeev	larl	%r9,sie_exit			# skip forward to sie_exit
178fbbdfca5SAlexander Gordeev	.endm
179b5415c8fSAlexander Gordeev#endif
180b5415c8fSAlexander Gordeev
1816dd85fbbSMartin Schwidefsky	GEN_BR_THUNK %r14
182f19fbd5eSMartin Schwidefsky
1834bfc86ceSHeiko Carstens	.section .kprobes.text, "ax"
18446210c44SHeiko Carstens.Ldummy:
18546210c44SHeiko Carstens	/*
18656e62a73SSven Schnelle	 * This nop exists only in order to avoid that __bpon starts at
18746210c44SHeiko Carstens	 * the beginning of the kprobes text section. In that case we would
18846210c44SHeiko Carstens	 * have several symbols at the same address. E.g. objdump would take
18946210c44SHeiko Carstens	 * an arbitrary symbol name when disassembling this code.
19056e62a73SSven Schnelle	 * With the added nop in between the __bpon symbol is unique
19146210c44SHeiko Carstens	 * again.
19246210c44SHeiko Carstens	 */
19346210c44SHeiko Carstens	nop	0
1944bfc86ceSHeiko Carstens
195d768bd89SMartin SchwidefskyENTRY(__bpon)
196d768bd89SMartin Schwidefsky	.globl __bpon
197d768bd89SMartin Schwidefsky	BPON
1986dd85fbbSMartin Schwidefsky	BR_EX	%r14
19926a374aeSMartin SchwidefskyENDPROC(__bpon)
200d768bd89SMartin Schwidefsky
2014bfc86ceSHeiko Carstens/*
2024bfc86ceSHeiko Carstens * Scheduler resume function, called by switch_to
2034bfc86ceSHeiko Carstens *  gpr2 = (task_struct *) prev
2044bfc86ceSHeiko Carstens *  gpr3 = (task_struct *) next
2054bfc86ceSHeiko Carstens * Returns:
2064bfc86ceSHeiko Carstens *  gpr2 = prev
2074bfc86ceSHeiko Carstens */
2084bfc86ceSHeiko CarstensENTRY(__switch_to)
2094bfc86ceSHeiko Carstens	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
2103241d3ebSHeiko Carstens	lghi	%r4,__TASK_stack
2113241d3ebSHeiko Carstens	lghi	%r1,__TASK_thread
2129fed920eSVasily Gorbik	llill	%r5,STACK_INIT
2133241d3ebSHeiko Carstens	stg	%r15,__THREAD_ksp(%r1,%r2)	# store kernel stack of prev
2149fed920eSVasily Gorbik	lg	%r15,0(%r4,%r3)			# start of kernel stack of next
2159fed920eSVasily Gorbik	agr	%r15,%r5			# end of kernel stack of next
2164bfc86ceSHeiko Carstens	stg	%r3,__LC_CURRENT		# store task struct of next
2174bfc86ceSHeiko Carstens	stg	%r15,__LC_KERNEL_STACK		# store end of kernel stack
2183241d3ebSHeiko Carstens	lg	%r15,__THREAD_ksp(%r1,%r3)	# load kernel stack of next
2193241d3ebSHeiko Carstens	aghi	%r3,__TASK_pid
2203241d3ebSHeiko Carstens	mvc	__LC_CURRENT_PID(4,%r0),0(%r3)	# store pid of next
2214bfc86ceSHeiko Carstens	lmg	%r6,%r15,__SF_GPRS(%r15)	# load gprs of next task
222fad442d3SHeiko Carstens	ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40
2236dd85fbbSMartin Schwidefsky	BR_EX	%r14
22426a374aeSMartin SchwidefskyENDPROC(__switch_to)
2254bfc86ceSHeiko Carstens
226d0fc4107SMartin Schwidefsky#if IS_ENABLED(CONFIG_KVM)
227d0fc4107SMartin Schwidefsky/*
228*6b33e68aSNico Boehr * __sie64a calling convention:
229*6b33e68aSNico Boehr * %r2 pointer to sie control block phys
230*6b33e68aSNico Boehr * %r3 pointer to sie control block virt
231*6b33e68aSNico Boehr * %r4 guest register save area
232d0fc4107SMartin Schwidefsky */
233*6b33e68aSNico BoehrENTRY(__sie64a)
234d0fc4107SMartin Schwidefsky	stmg	%r6,%r14,__SF_GPRS(%r15)	# save kernel registers
2356b73044bSMartin Schwidefsky	lg	%r12,__LC_CURRENT
236*6b33e68aSNico Boehr	stg	%r2,__SF_SIE_CONTROL_PHYS(%r15)	# save sie block physical..
237*6b33e68aSNico Boehr	stg	%r3,__SF_SIE_CONTROL(%r15)	# ...and virtual addresses
238*6b33e68aSNico Boehr	stg	%r4,__SF_SIE_SAVEAREA(%r15)	# save guest register save area
23992fa7a13SMartin Schwidefsky	xc	__SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0
24092fa7a13SMartin Schwidefsky	mvc	__SF_SIE_FLAGS(8,%r15),__TI_flags(%r12) # copy thread flags
241*6b33e68aSNico Boehr	lmg	%r0,%r13,0(%r4)			# load guest gprs 0-13
242d0fc4107SMartin Schwidefsky	lg	%r14,__LC_GMAP			# get gmap pointer
243d0fc4107SMartin Schwidefsky	ltgr	%r14,%r14
244d0fc4107SMartin Schwidefsky	jz	.Lsie_gmap
245d0fc4107SMartin Schwidefsky	lctlg	%c1,%c1,__GMAP_ASCE(%r14)	# load primary asce
246d0fc4107SMartin Schwidefsky.Lsie_gmap:
24792fa7a13SMartin Schwidefsky	lg	%r14,__SF_SIE_CONTROL(%r15)	# get control block pointer
248d0fc4107SMartin Schwidefsky	oi	__SIE_PROG0C+3(%r14),1		# we are going into SIE now
249d0fc4107SMartin Schwidefsky	tm	__SIE_PROG20+3(%r14),3		# last exit...
250d0fc4107SMartin Schwidefsky	jnz	.Lsie_skip
25183abeffbSHendrik Brueckner	TSTMSK	__LC_CPU_FLAGS,_CIF_FPU
252d0fc4107SMartin Schwidefsky	jo	.Lsie_skip			# exit if fp/vx regs changed
253*6b33e68aSNico Boehr	lg	%r14,__SF_SIE_CONTROL_PHYS(%r15)	# get sie block phys addr
25492fa7a13SMartin Schwidefsky	BPEXIT	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
255c929500dSQingFeng Hao.Lsie_entry:
256d0fc4107SMartin Schwidefsky	sie	0(%r14)
25729ccaa4bSAlexander Gordeev# Let the next instruction be NOP to avoid triggering a machine check
25829ccaa4bSAlexander Gordeev# and handling it in a guest as result of the instruction execution.
25929ccaa4bSAlexander Gordeev	nopr	7
26029ccaa4bSAlexander Gordeev.Lsie_leave:
261d768bd89SMartin Schwidefsky	BPOFF
26292fa7a13SMartin Schwidefsky	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
263d0fc4107SMartin Schwidefsky.Lsie_skip:
264*6b33e68aSNico Boehr	lg	%r14,__SF_SIE_CONTROL(%r15)	# get control block pointer
265d0fc4107SMartin Schwidefsky	ni	__SIE_PROG0C+3(%r14),0xfe	# no longer in SIE
26687d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE	# load primary asce
267d0fc4107SMartin Schwidefsky.Lsie_done:
268d0fc4107SMartin Schwidefsky# some program checks are suppressing. C code (e.g. do_protection_exception)
269c0e7bb38SChristian Borntraeger# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
270c0e7bb38SChristian Borntraeger# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
271*6b33e68aSNico Boehr# Other instructions between __sie64a and .Lsie_done should not cause program
272c0e7bb38SChristian Borntraeger# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
273c0e7bb38SChristian Borntraeger.Lrewind_pad6:
274c0e7bb38SChristian Borntraeger	nopr	7
275c0e7bb38SChristian Borntraeger.Lrewind_pad4:
276c0e7bb38SChristian Borntraeger	nopr	7
277c0e7bb38SChristian Borntraeger.Lrewind_pad2:
278c0e7bb38SChristian Borntraeger	nopr	7
279d0fc4107SMartin Schwidefsky	.globl sie_exit
280d0fc4107SMartin Schwidefskysie_exit:
28192fa7a13SMartin Schwidefsky	lg	%r14,__SF_SIE_SAVEAREA(%r15)	# load guest register save area
282d0fc4107SMartin Schwidefsky	stmg	%r0,%r13,0(%r14)		# save guest gprs 0-13
2837041d281SMartin Schwidefsky	xgr	%r0,%r0				# clear guest registers to
2847041d281SMartin Schwidefsky	xgr	%r1,%r1				# prevent speculative use
2857041d281SMartin Schwidefsky	xgr	%r3,%r3
2867041d281SMartin Schwidefsky	xgr	%r4,%r4
2877041d281SMartin Schwidefsky	xgr	%r5,%r5
288d0fc4107SMartin Schwidefsky	lmg	%r6,%r14,__SF_GPRS(%r15)	# restore kernel registers
28992fa7a13SMartin Schwidefsky	lg	%r2,__SF_SIE_REASON(%r15)	# return exit reason code
2906dd85fbbSMartin Schwidefsky	BR_EX	%r14
291d0fc4107SMartin Schwidefsky.Lsie_fault:
292d0fc4107SMartin Schwidefsky	lghi	%r14,-EFAULT
29392fa7a13SMartin Schwidefsky	stg	%r14,__SF_SIE_REASON(%r15)	# set exit reason code
294d0fc4107SMartin Schwidefsky	j	sie_exit
295d0fc4107SMartin Schwidefsky
296c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad6,.Lsie_fault)
297c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad4,.Lsie_fault)
298c0e7bb38SChristian Borntraeger	EX_TABLE(.Lrewind_pad2,.Lsie_fault)
299d0fc4107SMartin Schwidefsky	EX_TABLE(sie_exit,.Lsie_fault)
300*6b33e68aSNico BoehrENDPROC(__sie64a)
301*6b33e68aSNico BoehrEXPORT_SYMBOL(__sie64a)
302711f5df7SAl ViroEXPORT_SYMBOL(sie_exit)
303d0fc4107SMartin Schwidefsky#endif
304d0fc4107SMartin Schwidefsky
3054bfc86ceSHeiko Carstens/*
3064bfc86ceSHeiko Carstens * SVC interrupt handler routine. System calls are synchronous events and
3077b7735c5SChristian Borntraeger * are entered with interrupts disabled.
3084bfc86ceSHeiko Carstens */
3094bfc86ceSHeiko Carstens
3104bfc86ceSHeiko CarstensENTRY(system_call)
31156e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
3124bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
313d768bd89SMartin Schwidefsky	BPOFF
31456e62a73SSven Schnelle	lghi	%r14,0
3154bfc86ceSHeiko Carstens.Lsysc_per:
3163b051e89SSven Schnelle	STBEAR	__LC_LAST_BREAK
31787d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
31856e62a73SSven Schnelle	lg	%r12,__LC_CURRENT
3194bfc86ceSHeiko Carstens	lg	%r15,__LC_KERNEL_STACK
3209365965dSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
32156e62a73SSven Schnelle	stmg	%r0,%r7,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
32256e62a73SSven Schnelle	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
323d3f46896SChristian Borntraeger	# clear user controlled register to prevent speculative use
324d3f46896SChristian Borntraeger	xgr	%r0,%r0
32556e62a73SSven Schnelle	xgr	%r1,%r1
32656e62a73SSven Schnelle	xgr	%r4,%r4
32756e62a73SSven Schnelle	xgr	%r5,%r5
32856e62a73SSven Schnelle	xgr	%r6,%r6
32956e62a73SSven Schnelle	xgr	%r7,%r7
33056e62a73SSven Schnelle	xgr	%r8,%r8
33156e62a73SSven Schnelle	xgr	%r9,%r9
33256e62a73SSven Schnelle	xgr	%r10,%r10
33356e62a73SSven Schnelle	xgr	%r11,%r11
33456e62a73SSven Schnelle	la	%r2,STACK_FRAME_OVERHEAD(%r15)	# pointer to pt_regs
335af9ad822SSven Schnelle	mvc	__PT_R8(64,%r2),__LC_SAVE_AREA_SYNC
3363b051e89SSven Schnelle	MBEAR	%r2
33756e62a73SSven Schnelle	lgr	%r3,%r14
33856e62a73SSven Schnelle	brasl	%r14,__do_syscall
33987d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_USER_ASCE
34056e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
3416b73044bSMartin Schwidefsky	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3423b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
34356e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
3444bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
3453b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
34626a374aeSMartin SchwidefskyENDPROC(system_call)
3474bfc86ceSHeiko Carstens
3484bfc86ceSHeiko Carstens#
3494bfc86ceSHeiko Carstens# a new process exits the kernel with ret_from_fork
3504bfc86ceSHeiko Carstens#
3514bfc86ceSHeiko CarstensENTRY(ret_from_fork)
35256e62a73SSven Schnelle	lgr	%r3,%r11
35356e62a73SSven Schnelle	brasl	%r14,__ret_from_fork
35456e62a73SSven Schnelle	lctlg	%c1,%c1,__LC_USER_ASCE
35556e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
35656e62a73SSven Schnelle	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
3573b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
35856e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
35956e62a73SSven Schnelle	stpt	__LC_EXIT_TIMER
3603b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
36126a374aeSMartin SchwidefskyENDPROC(ret_from_fork)
36226a374aeSMartin Schwidefsky
3634bfc86ceSHeiko Carstens/*
3644bfc86ceSHeiko Carstens * Program check handler routine
3654bfc86ceSHeiko Carstens */
3664bfc86ceSHeiko Carstens
3674bfc86ceSHeiko CarstensENTRY(pgm_check_handler)
36856e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
369d768bd89SMartin Schwidefsky	BPOFF
3704bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
37156e62a73SSven Schnelle	lg	%r12,__LC_CURRENT
37256e62a73SSven Schnelle	lghi	%r10,0
3734bfc86ceSHeiko Carstens	lmg	%r8,%r9,__LC_PGM_OLD_PSW
37487d59863SHeiko Carstens	tmhh	%r8,0x0001		# coming from user space?
37587d59863SHeiko Carstens	jno	.Lpgm_skip_asce
37687d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_KERNEL_ASCE
37756e62a73SSven Schnelle	j	3f			# -> fault in user space
37887d59863SHeiko Carstens.Lpgm_skip_asce:
379d0fc4107SMartin Schwidefsky#if IS_ENABLED(CONFIG_KVM)
380*6b33e68aSNico Boehr	# cleanup critical section for program checks in __sie64a
381b5415c8fSAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,1f
382fbbdfca5SAlexander Gordeev	SIEEXIT
38356e62a73SSven Schnelle	lghi	%r10,_PIF_GUEST_FAULT
384d0fc4107SMartin Schwidefsky#endif
3850b38b5e1SSven Schnelle1:	tmhh	%r8,0x4000		# PER bit set in old PSW ?
3860b38b5e1SSven Schnelle	jnz	2f			# -> enabled, can't be a double fault
3874bfc86ceSHeiko Carstens	tm	__LC_PGM_ILC+3,0x80	# check for per exception
3884bfc86ceSHeiko Carstens	jnz	.Lpgm_svcper		# -> single stepped svc
3890b38b5e1SSven Schnelle2:	CHECK_STACK __LC_SAVE_AREA_SYNC
3904bfc86ceSHeiko Carstens	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
39156e62a73SSven Schnelle	# CHECK_VMAP_STACK branches to stack_overflow or 4f
39256e62a73SSven Schnelle	CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f
39356e62a73SSven Schnelle3:	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
3944bfc86ceSHeiko Carstens	lg	%r15,__LC_KERNEL_STACK
39556e62a73SSven Schnelle4:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
39656e62a73SSven Schnelle	stg	%r10,__PT_FLAGS(%r11)
39756e62a73SSven Schnelle	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
3984bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
39956e62a73SSven Schnelle	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
4003b051e89SSven Schnelle	mvc	__PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK
40156e62a73SSven Schnelle	stmg	%r8,%r9,__PT_PSW(%r11)
40256e62a73SSven Schnelle
4037041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
4047041d281SMartin Schwidefsky	xgr	%r0,%r0
4057041d281SMartin Schwidefsky	xgr	%r1,%r1
4067041d281SMartin Schwidefsky	xgr	%r3,%r3
4077041d281SMartin Schwidefsky	xgr	%r4,%r4
4087041d281SMartin Schwidefsky	xgr	%r5,%r5
4097041d281SMartin Schwidefsky	xgr	%r6,%r6
4107041d281SMartin Schwidefsky	xgr	%r7,%r7
41156e62a73SSven Schnelle	lgr	%r2,%r11
41256e62a73SSven Schnelle	brasl	%r14,__do_pgm_check
41356e62a73SSven Schnelle	tmhh	%r8,0x0001		# returning to user space?
41456e62a73SSven Schnelle	jno	.Lpgm_exit_kernel
41556e62a73SSven Schnelle	lctlg	%c1,%c1,__LC_USER_ASCE
41656e62a73SSven Schnelle	BPEXIT __TI_flags(%r12),_TIF_ISOLATE_BP
4170cd9b723SHeiko Carstens	stpt	__LC_EXIT_TIMER
41856e62a73SSven Schnelle.Lpgm_exit_kernel:
41956e62a73SSven Schnelle	mvc	__LC_RETURN_PSW(16),STACK_FRAME_OVERHEAD+__PT_PSW(%r15)
4203b051e89SSven Schnelle	LBEAR	STACK_FRAME_OVERHEAD+__PT_LAST_BREAK(%r15)
42156e62a73SSven Schnelle	lmg	%r0,%r15,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
4223b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
4234bfc86ceSHeiko Carstens
4244bfc86ceSHeiko Carstens#
4254bfc86ceSHeiko Carstens# single stepped system call
4264bfc86ceSHeiko Carstens#
4274bfc86ceSHeiko Carstens.Lpgm_svcper:
4284bfc86ceSHeiko Carstens	mvc	__LC_RETURN_PSW(8),__LC_SVC_NEW_PSW
4294bfc86ceSHeiko Carstens	larl	%r14,.Lsysc_per
4304bfc86ceSHeiko Carstens	stg	%r14,__LC_RETURN_PSW+8
43156e62a73SSven Schnelle	lghi	%r14,1
4323b051e89SSven Schnelle	LBEAR	__LC_PGM_LAST_BREAK
4333b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE # branch to .Lsysc_per
43426a374aeSMartin SchwidefskyENDPROC(pgm_check_handler)
4354bfc86ceSHeiko Carstens
4364bfc86ceSHeiko Carstens/*
43756e62a73SSven Schnelle * Interrupt handler macro used for external and IO interrupts.
4384bfc86ceSHeiko Carstens */
43956e62a73SSven Schnelle.macro INT_HANDLER name,lc_old_psw,handler
44056e62a73SSven SchnelleENTRY(\name)
44110bc15baSVasily Gorbik	stckf	__LC_INT_CLOCK
44256e62a73SSven Schnelle	stpt	__LC_SYS_ENTER_TIMER
4433b051e89SSven Schnelle	STBEAR	__LC_LAST_BREAK
444d768bd89SMartin Schwidefsky	BPOFF
4454bfc86ceSHeiko Carstens	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
446d5c352cdSHeiko Carstens	lg	%r12,__LC_CURRENT
44756e62a73SSven Schnelle	lmg	%r8,%r9,\lc_old_psw
448b0d31159SSven Schnelle	tmhh	%r8,0x0001			# interrupting from user ?
449b0d31159SSven Schnelle	jnz	1f
450b0d31159SSven Schnelle#if IS_ENABLED(CONFIG_KVM)
451b5415c8fSAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,0f
452fbbdfca5SAlexander Gordeev	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
453fbbdfca5SAlexander Gordeev	SIEEXIT
454b0d31159SSven Schnelle#endif
455b0d31159SSven Schnelle0:	CHECK_STACK __LC_SAVE_AREA_ASYNC
456b0d31159SSven Schnelle	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
457b0d31159SSven Schnelle	j	2f
458b0d31159SSven Schnelle1:	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
459b0d31159SSven Schnelle	lctlg	%c1,%c1,__LC_KERNEL_ASCE
460b0d31159SSven Schnelle	lg	%r15,__LC_KERNEL_STACK
461b74e409eSVasily Gorbik2:	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
462b74e409eSVasily Gorbik	la	%r11,STACK_FRAME_OVERHEAD(%r15)
4634bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
4647041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
4657041d281SMartin Schwidefsky	xgr	%r0,%r0
4667041d281SMartin Schwidefsky	xgr	%r1,%r1
4677041d281SMartin Schwidefsky	xgr	%r3,%r3
4687041d281SMartin Schwidefsky	xgr	%r4,%r4
4697041d281SMartin Schwidefsky	xgr	%r5,%r5
4707041d281SMartin Schwidefsky	xgr	%r6,%r6
4717041d281SMartin Schwidefsky	xgr	%r7,%r7
4727041d281SMartin Schwidefsky	xgr	%r10,%r10
473ca1f4d70SSven Schnelle	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
4744bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
4753b051e89SSven Schnelle	MBEAR	%r11
4764bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
47729b06ad7SHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
47856e62a73SSven Schnelle	brasl	%r14,\handler
4794bfc86ceSHeiko Carstens	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r11)
48056e62a73SSven Schnelle	tmhh	%r8,0x0001		# returning to user ?
48156e62a73SSven Schnelle	jno	2f
48287d59863SHeiko Carstens	lctlg	%c1,%c1,__LC_USER_ASCE
4836b73044bSMartin Schwidefsky	BPEXIT	__TI_flags(%r12),_TIF_ISOLATE_BP
4844bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
4853b051e89SSven Schnelle2:	LBEAR	__PT_LAST_BREAK(%r11)
4863b051e89SSven Schnelle	lmg	%r0,%r15,__PT_R0(%r11)
4873b051e89SSven Schnelle	LPSWEY	__LC_RETURN_PSW,__LC_RETURN_LPSWE
48856e62a73SSven SchnelleENDPROC(\name)
48956e62a73SSven Schnelle.endm
4904bfc86ceSHeiko Carstens
49156e62a73SSven SchnelleINT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
49256e62a73SSven SchnelleINT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
4934bfc86ceSHeiko Carstens
4944bfc86ceSHeiko Carstens/*
4950b0ed657SSven Schnelle * Load idle PSW.
4964bfc86ceSHeiko Carstens */
4974bfc86ceSHeiko CarstensENTRY(psw_idle)
498a994eddbSVasily Gorbik	stg	%r14,(__SF_GPRS+8*8)(%r15)
4994bfc86ceSHeiko Carstens	stg	%r3,__SF_EMPTY(%r15)
50056e62a73SSven Schnelle	larl	%r1,psw_idle_exit
5014bfc86ceSHeiko Carstens	stg	%r1,__SF_EMPTY+8(%r15)
50272d38b19SMartin Schwidefsky	larl	%r1,smp_cpu_mtid
50372d38b19SMartin Schwidefsky	llgf	%r1,0(%r1)
50472d38b19SMartin Schwidefsky	ltgr	%r1,%r1
50572d38b19SMartin Schwidefsky	jz	.Lpsw_idle_stcctm
50656e62a73SSven Schnelle	.insn	rsy,0xeb0000000017,%r1,5,__MT_CYCLES_ENTER(%r2)
50772d38b19SMartin Schwidefsky.Lpsw_idle_stcctm:
508419123f9SMartin Schwidefsky	oi	__LC_CPU_FLAGS+7,_CIF_ENABLED_WAIT
509d768bd89SMartin Schwidefsky	BPON
51010bc15baSVasily Gorbik	stckf	__CLOCK_IDLE_ENTER(%r2)
5114bfc86ceSHeiko Carstens	stpt	__TIMER_IDLE_ENTER(%r2)
5124bfc86ceSHeiko Carstens	lpswe	__SF_EMPTY(%r15)
51356e62a73SSven Schnelle.globl psw_idle_exit
51456e62a73SSven Schnellepsw_idle_exit:
5156dd85fbbSMartin Schwidefsky	BR_EX	%r14
51626a374aeSMartin SchwidefskyENDPROC(psw_idle)
5174bfc86ceSHeiko Carstens
518b5510d9bSHendrik Brueckner/*
5194bfc86ceSHeiko Carstens * Machine check handler routines
5204bfc86ceSHeiko Carstens */
5214bfc86ceSHeiko CarstensENTRY(mcck_int_handler)
52210bc15baSVasily Gorbik	stckf	__LC_MCCK_CLOCK
523d768bd89SMartin Schwidefsky	BPOFF
5243037a52fSMartin Schwidefsky	la	%r1,4095		# validate r1
5253037a52fSMartin Schwidefsky	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# validate cpu timer
5263b051e89SSven Schnelle	LBEAR	__LC_LAST_BREAK_SAVE_AREA-4095(%r1)		# validate bear
5273037a52fSMartin Schwidefsky	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# validate gprs
528d5c352cdSHeiko Carstens	lg	%r12,__LC_CURRENT
5294bfc86ceSHeiko Carstens	lmg	%r8,%r9,__LC_MCK_OLD_PSW
53083abeffbSHendrik Brueckner	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE
5314bfc86ceSHeiko Carstens	jo	.Lmcck_panic		# yes -> rest of mcck code invalid
5323037a52fSMartin Schwidefsky	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_CR_VALID
5333037a52fSMartin Schwidefsky	jno	.Lmcck_panic		# control registers invalid -> panic
5343037a52fSMartin Schwidefsky	la	%r14,4095
5353037a52fSMartin Schwidefsky	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r14) # validate ctl regs
5363037a52fSMartin Schwidefsky	ptlb
5375fa2ea07SAlexander Gordeev	lghi	%r14,__LC_CPU_TIMER_SAVE_AREA
5384bfc86ceSHeiko Carstens	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
53983abeffbSHendrik Brueckner	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_CPU_TIMER_VALID
5404bfc86ceSHeiko Carstens	jo	3f
54156e62a73SSven Schnelle	la	%r14,__LC_SYS_ENTER_TIMER
54256e62a73SSven Schnelle	clc	0(8,%r14),__LC_EXIT_TIMER
5434bfc86ceSHeiko Carstens	jl	1f
5444bfc86ceSHeiko Carstens	la	%r14,__LC_EXIT_TIMER
5454bfc86ceSHeiko Carstens1:	clc	0(8,%r14),__LC_LAST_UPDATE_TIMER
5464bfc86ceSHeiko Carstens	jl	2f
5474bfc86ceSHeiko Carstens	la	%r14,__LC_LAST_UPDATE_TIMER
5484bfc86ceSHeiko Carstens2:	spt	0(%r14)
5494bfc86ceSHeiko Carstens	mvc	__LC_MCCK_ENTER_TIMER(8),0(%r14)
5503037a52fSMartin Schwidefsky3:	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_PSW_MWP_VALID
5513037a52fSMartin Schwidefsky	jno	.Lmcck_panic
5523037a52fSMartin Schwidefsky	tmhh	%r8,0x0001		# interrupting from user ?
553d35925b3SAlexander Gordeev	jnz	6f
5543037a52fSMartin Schwidefsky	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID
5553037a52fSMartin Schwidefsky	jno	.Lmcck_panic
556b0d31159SSven Schnelle#if IS_ENABLED(CONFIG_KVM)
557d35925b3SAlexander Gordeev	OUTSIDE	%r9,.Lsie_gmap,.Lsie_done,6f
55829ccaa4bSAlexander Gordeev	OUTSIDE	%r9,.Lsie_entry,.Lsie_leave,4f
55920232b18SAlexander Gordeev	oi	__LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
560d35925b3SAlexander Gordeev	j	5f
561d35925b3SAlexander Gordeev4:	CHKSTG	.Lmcck_panic
562d35925b3SAlexander Gordeev5:	larl	%r14,.Lstosm_tmp
563d35925b3SAlexander Gordeev	stosm	0(%r14),0x04		# turn dat on, keep irqs off
564d35925b3SAlexander Gordeev	BPENTER	__SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
565fbbdfca5SAlexander Gordeev	SIEEXIT
566b61b1595SSven Schnelle	j	.Lmcck_stack
567e2c13d64SAlexander Gordeev#endif
568d35925b3SAlexander Gordeev6:	CHKSTG	.Lmcck_panic
569d35925b3SAlexander Gordeev	larl	%r14,.Lstosm_tmp
570d35925b3SAlexander Gordeev	stosm	0(%r14),0x04		# turn dat on, keep irqs off
571d35925b3SAlexander Gordeev	tmhh	%r8,0x0001		# interrupting from user ?
572d35925b3SAlexander Gordeev	jz	.Lmcck_stack
573b0d31159SSven Schnelle	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
574b61b1595SSven Schnelle.Lmcck_stack:
575b61b1595SSven Schnelle	lg	%r15,__LC_MCCK_STACK
576b61b1595SSven Schnelle	la	%r11,STACK_FRAME_OVERHEAD(%r15)
57726521412SSven Schnelle	stctg	%c1,%c1,__PT_CR1(%r11)
578b61b1595SSven Schnelle	lctlg	%c1,%c1,__LC_KERNEL_ASCE
579b61b1595SSven Schnelle	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
5804bfc86ceSHeiko Carstens	lghi	%r14,__LC_GPREGS_SAVE_AREA+64
5814bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
5827041d281SMartin Schwidefsky	# clear user controlled registers to prevent speculative use
5837041d281SMartin Schwidefsky	xgr	%r0,%r0
5847041d281SMartin Schwidefsky	xgr	%r1,%r1
5857041d281SMartin Schwidefsky	xgr	%r3,%r3
5867041d281SMartin Schwidefsky	xgr	%r4,%r4
5877041d281SMartin Schwidefsky	xgr	%r5,%r5
5887041d281SMartin Schwidefsky	xgr	%r6,%r6
5897041d281SMartin Schwidefsky	xgr	%r7,%r7
5907041d281SMartin Schwidefsky	xgr	%r10,%r10
5914bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),0(%r14)
5924bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
5934bfc86ceSHeiko Carstens	xc	__PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
5944bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
5954bfc86ceSHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
5964bfc86ceSHeiko Carstens	brasl	%r14,s390_do_machine_check
5970b0ed657SSven Schnelle	cghi	%r2,0
5980b0ed657SSven Schnelle	je	.Lmcck_return
5994bfc86ceSHeiko Carstens	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
6004bfc86ceSHeiko Carstens	mvc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
6014bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
6024bfc86ceSHeiko Carstens	la	%r11,STACK_FRAME_OVERHEAD(%r1)
60339d62336SThomas Richter	lgr	%r2,%r11
6044bfc86ceSHeiko Carstens	lgr	%r15,%r1
6054bfc86ceSHeiko Carstens	brasl	%r14,s390_handle_mcck
6064bfc86ceSHeiko Carstens.Lmcck_return:
60787d59863SHeiko Carstens	lctlg	%c1,%c1,__PT_CR1(%r11)
6084bfc86ceSHeiko Carstens	lmg	%r0,%r10,__PT_R0(%r11)
6094bfc86ceSHeiko Carstens	mvc	__LC_RETURN_MCCK_PSW(16),__PT_PSW(%r11) # move return PSW
6104bfc86ceSHeiko Carstens	tm	__LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
6114bfc86ceSHeiko Carstens	jno	0f
6126b73044bSMartin Schwidefsky	BPEXIT	__TI_flags(%r12),_TIF_ISOLATE_BP
6134bfc86ceSHeiko Carstens	stpt	__LC_EXIT_TIMER
614fad442d3SHeiko Carstens0:	ALTERNATIVE "nop", __stringify(lghi %r12,__LC_LAST_BREAK_SAVE_AREA),193
6153b051e89SSven Schnelle	LBEAR	0(%r12)
6163b051e89SSven Schnelle	lmg	%r11,%r15,__PT_R11(%r11)
6173b051e89SSven Schnelle	LPSWEY	__LC_RETURN_MCCK_PSW,__LC_RETURN_MCCK_LPSWE
6184bfc86ceSHeiko Carstens
6194bfc86ceSHeiko Carstens.Lmcck_panic:
6207f6dc8d4SAlexander Gordeev	/*
6217f6dc8d4SAlexander Gordeev	 * Iterate over all possible CPU addresses in the range 0..0xffff
6227f6dc8d4SAlexander Gordeev	 * and stop each CPU using signal processor. Use compare and swap
6237f6dc8d4SAlexander Gordeev	 * to allow just one CPU-stopper and prevent concurrent CPUs from
6247f6dc8d4SAlexander Gordeev	 * stopping each other while leaving the others running.
6257f6dc8d4SAlexander Gordeev	 */
6267f6dc8d4SAlexander Gordeev	lhi	%r5,0
6277f6dc8d4SAlexander Gordeev	lhi	%r6,1
6287f6dc8d4SAlexander Gordeev	larl	%r7,.Lstop_lock
6297f6dc8d4SAlexander Gordeev	cs	%r5,%r6,0(%r7)		# single CPU-stopper only
6307f6dc8d4SAlexander Gordeev	jnz	4f
6317f6dc8d4SAlexander Gordeev	larl	%r7,.Lthis_cpu
6327f6dc8d4SAlexander Gordeev	stap	0(%r7)			# this CPU address
6337f6dc8d4SAlexander Gordeev	lh	%r4,0(%r7)
6347f6dc8d4SAlexander Gordeev	nilh	%r4,0
6357f6dc8d4SAlexander Gordeev	lhi	%r0,1
6367f6dc8d4SAlexander Gordeev	sll	%r0,16			# CPU counter
6377f6dc8d4SAlexander Gordeev	lhi	%r3,0			# next CPU address
6387f6dc8d4SAlexander Gordeev0:	cr	%r3,%r4
6397f6dc8d4SAlexander Gordeev	je	2f
6407f6dc8d4SAlexander Gordeev1:	sigp	%r1,%r3,SIGP_STOP	# stop next CPU
6417f6dc8d4SAlexander Gordeev	brc	SIGP_CC_BUSY,1b
6427f6dc8d4SAlexander Gordeev2:	ahi	%r3,1
6437f6dc8d4SAlexander Gordeev	brct	%r0,0b
6447f6dc8d4SAlexander Gordeev3:	sigp	%r1,%r4,SIGP_STOP	# stop this CPU
6457f6dc8d4SAlexander Gordeev	brc	SIGP_CC_BUSY,3b
6467f6dc8d4SAlexander Gordeev4:	j	4b
64726a374aeSMartin SchwidefskyENDPROC(mcck_int_handler)
6484bfc86ceSHeiko Carstens
6494bfc86ceSHeiko CarstensENTRY(restart_int_handler)
650fad442d3SHeiko Carstens	ALTERNATIVE "nop", "lpp _LPP_OFFSET", 40
651e5b98199SMartin Schwidefsky	stg	%r15,__LC_SAVE_AREA_RESTART
652915fea04SAlexander Gordeev	TSTMSK	__LC_RESTART_FLAGS,RESTART_FLAG_CTLREGS,4
653915fea04SAlexander Gordeev	jz	0f
654915fea04SAlexander Gordeev	la	%r15,4095
655915fea04SAlexander Gordeev	lctlg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r15)
656915fea04SAlexander Gordeev0:	larl	%r15,.Lstosm_tmp
657915fea04SAlexander Gordeev	stosm	0(%r15),0x04			# turn dat on, keep irqs off
6584bfc86ceSHeiko Carstens	lg	%r15,__LC_RESTART_STACK
659ce3dc447SMartin Schwidefsky	xc	STACK_FRAME_OVERHEAD(__PT_SIZE,%r15),STACK_FRAME_OVERHEAD(%r15)
660ce3dc447SMartin Schwidefsky	stmg	%r0,%r14,STACK_FRAME_OVERHEAD+__PT_R0(%r15)
661ce3dc447SMartin Schwidefsky	mvc	STACK_FRAME_OVERHEAD+__PT_R15(8,%r15),__LC_SAVE_AREA_RESTART
662ce3dc447SMartin Schwidefsky	mvc	STACK_FRAME_OVERHEAD+__PT_PSW(16,%r15),__LC_RST_OLD_PSW
6634bfc86ceSHeiko Carstens	xc	0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
6644bfc86ceSHeiko Carstens	lg	%r1,__LC_RESTART_FN		# load fn, parm & source cpu
6654bfc86ceSHeiko Carstens	lg	%r2,__LC_RESTART_DATA
666915fea04SAlexander Gordeev	lgf	%r3,__LC_RESTART_SOURCE
6674bfc86ceSHeiko Carstens	ltgr	%r3,%r3				# test source cpu address
6684bfc86ceSHeiko Carstens	jm	1f				# negative -> skip source stop
6694bfc86ceSHeiko Carstens0:	sigp	%r4,%r3,SIGP_SENSE		# sigp sense to source cpu
6704bfc86ceSHeiko Carstens	brc	10,0b				# wait for status stored
6714bfc86ceSHeiko Carstens1:	basr	%r14,%r1			# call function
6724bfc86ceSHeiko Carstens	stap	__SF_EMPTY(%r15)		# store cpu address
6734bfc86ceSHeiko Carstens	llgh	%r3,__SF_EMPTY(%r15)
6744bfc86ceSHeiko Carstens2:	sigp	%r4,%r3,SIGP_STOP		# sigp stop to current cpu
6754bfc86ceSHeiko Carstens	brc	2,2b
6764bfc86ceSHeiko Carstens3:	j	3b
67726a374aeSMartin SchwidefskyENDPROC(restart_int_handler)
6784bfc86ceSHeiko Carstens
6794bfc86ceSHeiko Carstens	.section .kprobes.text, "ax"
6804bfc86ceSHeiko Carstens
681ce3dc447SMartin Schwidefsky#if defined(CONFIG_CHECK_STACK) || defined(CONFIG_VMAP_STACK)
6824bfc86ceSHeiko Carstens/*
6834bfc86ceSHeiko Carstens * The synchronous or the asynchronous stack overflowed. We are dead.
6844bfc86ceSHeiko Carstens * No need to properly save the registers, we are going to panic anyway.
6854bfc86ceSHeiko Carstens * Setup a pt_regs so that show_trace can provide a good call trace.
6864bfc86ceSHeiko Carstens */
68726a374aeSMartin SchwidefskyENTRY(stack_overflow)
688ce3dc447SMartin Schwidefsky	lg	%r15,__LC_NODAT_STACK	# change to panic stack
6894bfc86ceSHeiko Carstens	la	%r11,STACK_FRAME_OVERHEAD(%r15)
6904bfc86ceSHeiko Carstens	stmg	%r0,%r7,__PT_R0(%r11)
6914bfc86ceSHeiko Carstens	stmg	%r8,%r9,__PT_PSW(%r11)
6924bfc86ceSHeiko Carstens	mvc	__PT_R8(64,%r11),0(%r14)
6934bfc86ceSHeiko Carstens	stg	%r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
6944bfc86ceSHeiko Carstens	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
6954bfc86ceSHeiko Carstens	lgr	%r2,%r11		# pass pointer to pt_regs
6964bfc86ceSHeiko Carstens	jg	kernel_stack_overflow
69726a374aeSMartin SchwidefskyENDPROC(stack_overflow)
6984bfc86ceSHeiko Carstens#endif
6994bfc86ceSHeiko Carstens
7007f6dc8d4SAlexander Gordeev	.section .data, "aw"
7017f6dc8d4SAlexander Gordeev		.align	4
7027f6dc8d4SAlexander Gordeev.Lstop_lock:	.long	0
7037f6dc8d4SAlexander Gordeev.Lthis_cpu:	.short	0
704d35925b3SAlexander Gordeev.Lstosm_tmp:	.byte	0
7054bfc86ceSHeiko Carstens	.section .rodata, "a"
706ff4a742dSGerald Schaefer#define SYSCALL(esame,emu)	.quad __s390x_ ## esame
7074bfc86ceSHeiko Carstens	.globl	sys_call_table
7084bfc86ceSHeiko Carstenssys_call_table:
7094381f9f1SHendrik Brueckner#include "asm/syscall_table.h"
7104bfc86ceSHeiko Carstens#undef SYSCALL
7114bfc86ceSHeiko Carstens
7124bfc86ceSHeiko Carstens#ifdef CONFIG_COMPAT
7134bfc86ceSHeiko Carstens
714ff4a742dSGerald Schaefer#define SYSCALL(esame,emu)	.quad __s390_ ## emu
7154bfc86ceSHeiko Carstens	.globl	sys_call_table_emu
7164bfc86ceSHeiko Carstenssys_call_table_emu:
7174381f9f1SHendrik Brueckner#include "asm/syscall_table.h"
7184bfc86ceSHeiko Carstens#undef SYSCALL
7194bfc86ceSHeiko Carstens#endif
720