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