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