xref: /openbmc/linux/arch/s390/kernel/text_amode31.S (revision 255490f9)
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Code that needs to run below 2 GB.
4 *
5 * Copyright IBM Corp. 2019
6 */
7
8#include <linux/linkage.h>
9#include <asm/asm-extable.h>
10#include <asm/errno.h>
11#include <asm/sigp.h>
12
13	.section .amode31.text,"ax"
14/*
15 * Simplified version of expoline thunk. The normal thunks can not be used here,
16 * because they might be more than 2 GB away, and not reachable by the relative
17 * branch. No comdat, exrl, etc. optimizations used here, because it only
18 * affects a few functions that are not performance-relevant.
19 */
20	.macro BR_EX_AMODE31_r14
21	larl	%r1,0f
22	ex	0,0(%r1)
23	j	.
240:	br	%r14
25	.endm
26
27/*
28 * int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode)
29 */
30ENTRY(_diag14_amode31)
31	lgr	%r1,%r2
32	lgr	%r2,%r3
33	lgr	%r3,%r4
34	lhi	%r5,-EIO
35	sam31
36	diag	%r1,%r2,0x14
37.Ldiag14_ex:
38	ipm	%r5
39	srl	%r5,28
40.Ldiag14_fault:
41	sam64
42	lgfr	%r2,%r5
43	BR_EX_AMODE31_r14
44	EX_TABLE_AMODE31(.Ldiag14_ex, .Ldiag14_fault)
45ENDPROC(_diag14_amode31)
46
47/*
48 * int _diag210_amode31(struct diag210 *addr)
49 */
50ENTRY(_diag210_amode31)
51	lgr	%r1,%r2
52	lhi	%r2,-1
53	sam31
54	diag	%r1,%r0,0x210
55.Ldiag210_ex:
56	ipm	%r2
57	srl	%r2,28
58.Ldiag210_fault:
59	sam64
60	lgfr	%r2,%r2
61	BR_EX_AMODE31_r14
62	EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault)
63ENDPROC(_diag210_amode31)
64
65/*
66 * int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode)
67 */
68ENTRY(_diag26c_amode31)
69	lghi	%r5,-EOPNOTSUPP
70	sam31
71	diag	%r2,%r4,0x26c
72.Ldiag26c_ex:
73	sam64
74	lgfr	%r2,%r5
75	BR_EX_AMODE31_r14
76	EX_TABLE_AMODE31(.Ldiag26c_ex, .Ldiag26c_ex)
77ENDPROC(_diag26c_amode31)
78
79/*
80 * void _diag0c_amode31(struct hypfs_diag0c_entry *entry)
81 */
82ENTRY(_diag0c_amode31)
83	sam31
84	diag	%r2,%r2,0x0c
85	sam64
86	BR_EX_AMODE31_r14
87ENDPROC(_diag0c_amode31)
88
89/*
90 * void _diag308_reset_amode31(void)
91 *
92 * Calls diag 308 subcode 1 and continues execution
93 */
94ENTRY(_diag308_reset_amode31)
95	larl	%r4,.Lctlregs		# Save control registers
96	stctg	%c0,%c15,0(%r4)
97	lg	%r2,0(%r4)		# Disable lowcore protection
98	nilh	%r2,0xefff
99	larl	%r4,.Lctlreg0
100	stg	%r2,0(%r4)
101	lctlg	%c0,%c0,0(%r4)
102	larl	%r4,.Lfpctl		# Floating point control register
103	stfpc	0(%r4)
104	larl	%r4,.Lprefix		# Save prefix register
105	stpx	0(%r4)
106	larl	%r4,.Lprefix_zero	# Set prefix register to 0
107	spx	0(%r4)
108	larl	%r4,.Lcontinue_psw	# Save PSW flags
109	epsw	%r2,%r3
110	stm	%r2,%r3,0(%r4)
111	larl	%r4,.Lrestart_part2	# Setup restart PSW at absolute 0
112	larl	%r3,.Lrestart_diag308_psw
113	og	%r4,0(%r3)		# Save PSW
114	lghi	%r3,0
115	sturg	%r4,%r3			# Use sturg, because of large pages
116	lghi	%r1,1
117	lghi	%r0,0
118	diag	%r0,%r1,0x308
119.Lrestart_part2:
120	lhi	%r0,0			# Load r0 with zero
121	lhi	%r1,2			# Use mode 2 = ESAME (dump)
122	sigp	%r1,%r0,SIGP_SET_ARCHITECTURE	# Switch to ESAME mode
123	sam64				# Switch to 64 bit addressing mode
124	larl	%r4,.Lctlregs		# Restore control registers
125	lctlg	%c0,%c15,0(%r4)
126	larl	%r4,.Lfpctl		# Restore floating point ctl register
127	lfpc	0(%r4)
128	larl	%r4,.Lprefix		# Restore prefix register
129	spx	0(%r4)
130	larl	%r4,.Lcontinue_psw	# Restore PSW flags
131	larl	%r2,.Lcontinue
132	stg	%r2,8(%r4)
133	lpswe	0(%r4)
134.Lcontinue:
135	BR_EX_AMODE31_r14
136ENDPROC(_diag308_reset_amode31)
137
138	.section .amode31.data,"aw",@progbits
139.align	8
140.Lrestart_diag308_psw:
141	.long	0x00080000,0x80000000
142
143.align 8
144.Lcontinue_psw:
145	.quad	0,0
146
147.align 8
148.Lctlreg0:
149	.quad	0
150.Lctlregs:
151	.rept	16
152	.quad	0
153	.endr
154.Lfpctl:
155	.long	0
156.Lprefix:
157	.long	0
158.Lprefix_zero:
159	.long	0
160