GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / s390 / cio / ioasm.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Channel subsystem I/O instructions.
4  */
5
6 #include <linux/export.h>
7
8 #include <asm/asm-extable.h>
9 #include <asm/chpid.h>
10 #include <asm/schid.h>
11 #include <asm/crw.h>
12
13 #include "ioasm.h"
14 #include "orb.h"
15 #include "cio.h"
16 #include "cio_inject.h"
17
18 static inline int __stsch(struct subchannel_id schid, struct schib *addr)
19 {
20         unsigned long r1 = *(unsigned int *)&schid;
21         int ccode = -EIO;
22
23         asm volatile(
24                 "       lgr     1,%[r1]\n"
25                 "       stsch   %[addr]\n"
26                 "0:     ipm     %[cc]\n"
27                 "       srl     %[cc],28\n"
28                 "1:\n"
29                 EX_TABLE(0b, 1b)
30                 : [cc] "+&d" (ccode), [addr] "=Q" (*addr)
31                 : [r1] "d" (r1)
32                 : "cc", "1");
33         return ccode;
34 }
35
36 int stsch(struct subchannel_id schid, struct schib *addr)
37 {
38         int ccode;
39
40         ccode = __stsch(schid, addr);
41         trace_s390_cio_stsch(schid, addr, ccode);
42
43         return ccode;
44 }
45 EXPORT_SYMBOL(stsch);
46
47 static inline int __msch(struct subchannel_id schid, struct schib *addr)
48 {
49         unsigned long r1 = *(unsigned int *)&schid;
50         int ccode = -EIO;
51
52         asm volatile(
53                 "       lgr     1,%[r1]\n"
54                 "       msch    %[addr]\n"
55                 "0:     ipm     %[cc]\n"
56                 "       srl     %[cc],28\n"
57                 "1:\n"
58                 EX_TABLE(0b, 1b)
59                 : [cc] "+&d" (ccode)
60                 : [r1] "d" (r1), [addr] "Q" (*addr)
61                 : "cc", "1");
62         return ccode;
63 }
64
65 int msch(struct subchannel_id schid, struct schib *addr)
66 {
67         int ccode;
68
69         ccode = __msch(schid, addr);
70         trace_s390_cio_msch(schid, addr, ccode);
71
72         return ccode;
73 }
74
75 static inline int __tsch(struct subchannel_id schid, struct irb *addr)
76 {
77         unsigned long r1 = *(unsigned int *)&schid;
78         int ccode;
79
80         asm volatile(
81                 "       lgr     1,%[r1]\n"
82                 "       tsch    %[addr]\n"
83                 "       ipm     %[cc]\n"
84                 "       srl     %[cc],28"
85                 : [cc] "=&d" (ccode), [addr] "=Q" (*addr)
86                 : [r1] "d" (r1)
87                 : "cc", "1");
88         return ccode;
89 }
90
91 int tsch(struct subchannel_id schid, struct irb *addr)
92 {
93         int ccode;
94
95         ccode = __tsch(schid, addr);
96         trace_s390_cio_tsch(schid, addr, ccode);
97
98         return ccode;
99 }
100
101 static inline int __ssch(struct subchannel_id schid, union orb *addr)
102 {
103         unsigned long r1 = *(unsigned int *)&schid;
104         int ccode = -EIO;
105
106         asm volatile(
107                 "       lgr     1,%[r1]\n"
108                 "       ssch    %[addr]\n"
109                 "0:     ipm     %[cc]\n"
110                 "       srl     %[cc],28\n"
111                 "1:\n"
112                 EX_TABLE(0b, 1b)
113                 : [cc] "+&d" (ccode)
114                 : [r1] "d" (r1), [addr] "Q" (*addr)
115                 : "cc", "memory", "1");
116         return ccode;
117 }
118
119 int ssch(struct subchannel_id schid, union orb *addr)
120 {
121         int ccode;
122
123         ccode = __ssch(schid, addr);
124         trace_s390_cio_ssch(schid, addr, ccode);
125
126         return ccode;
127 }
128 EXPORT_SYMBOL(ssch);
129
130 static inline int __csch(struct subchannel_id schid)
131 {
132         unsigned long r1 = *(unsigned int *)&schid;
133         int ccode;
134
135         asm volatile(
136                 "       lgr     1,%[r1]\n"
137                 "       csch\n"
138                 "       ipm     %[cc]\n"
139                 "       srl     %[cc],28\n"
140                 : [cc] "=&d" (ccode)
141                 : [r1] "d" (r1)
142                 : "cc", "1");
143         return ccode;
144 }
145
146 int csch(struct subchannel_id schid)
147 {
148         int ccode;
149
150         ccode = __csch(schid);
151         trace_s390_cio_csch(schid, ccode);
152
153         return ccode;
154 }
155 EXPORT_SYMBOL(csch);
156
157 int tpi(struct tpi_info *addr)
158 {
159         int ccode;
160
161         asm volatile(
162                 "       tpi     %[addr]\n"
163                 "       ipm     %[cc]\n"
164                 "       srl     %[cc],28"
165                 : [cc] "=&d" (ccode), [addr] "=Q" (*addr)
166                 :
167                 : "cc");
168         trace_s390_cio_tpi(addr, ccode);
169
170         return ccode;
171 }
172
173 int chsc(void *chsc_area)
174 {
175         typedef struct { char _[4096]; } addr_type;
176         int cc = -EIO;
177
178         asm volatile(
179                 "       .insn   rre,0xb25f0000,%[chsc_area],0\n"
180                 "0:     ipm     %[cc]\n"
181                 "       srl     %[cc],28\n"
182                 "1:\n"
183                 EX_TABLE(0b, 1b)
184                 : [cc] "+&d" (cc), "+m" (*(addr_type *)chsc_area)
185                 : [chsc_area] "d" (chsc_area)
186                 : "cc");
187         trace_s390_cio_chsc(chsc_area, cc);
188
189         return cc;
190 }
191 EXPORT_SYMBOL(chsc);
192
193 static inline int __rsch(struct subchannel_id schid)
194 {
195         unsigned long r1 = *(unsigned int *)&schid;
196         int ccode;
197
198         asm volatile(
199                 "       lgr     1,%[r1]\n"
200                 "       rsch\n"
201                 "       ipm     %[cc]\n"
202                 "       srl     %[cc],28\n"
203                 : [cc] "=&d" (ccode)
204                 : [r1] "d" (r1)
205                 : "cc", "memory", "1");
206         return ccode;
207 }
208
209 int rsch(struct subchannel_id schid)
210 {
211         int ccode;
212
213         ccode = __rsch(schid);
214         trace_s390_cio_rsch(schid, ccode);
215
216         return ccode;
217 }
218
219 static inline int __hsch(struct subchannel_id schid)
220 {
221         unsigned long r1 = *(unsigned int *)&schid;
222         int ccode;
223
224         asm volatile(
225                 "       lgr     1,%[r1]\n"
226                 "       hsch\n"
227                 "       ipm     %[cc]\n"
228                 "       srl     %[cc],28\n"
229                 : [cc] "=&d" (ccode)
230                 : [r1] "d" (r1)
231                 : "cc", "1");
232         return ccode;
233 }
234
235 int hsch(struct subchannel_id schid)
236 {
237         int ccode;
238
239         ccode = __hsch(schid);
240         trace_s390_cio_hsch(schid, ccode);
241
242         return ccode;
243 }
244 EXPORT_SYMBOL(hsch);
245
246 static inline int __xsch(struct subchannel_id schid)
247 {
248         unsigned long r1 = *(unsigned int *)&schid;
249         int ccode;
250
251         asm volatile(
252                 "       lgr     1,%[r1]\n"
253                 "       xsch\n"
254                 "       ipm     %[cc]\n"
255                 "       srl     %[cc],28\n"
256                 : [cc] "=&d" (ccode)
257                 : [r1] "d" (r1)
258                 : "cc", "1");
259         return ccode;
260 }
261
262 int xsch(struct subchannel_id schid)
263 {
264         int ccode;
265
266         ccode = __xsch(schid);
267         trace_s390_cio_xsch(schid, ccode);
268
269         return ccode;
270 }
271
272 static inline int __stcrw(struct crw *crw)
273 {
274         int ccode;
275
276         asm volatile(
277                 "       stcrw   %[crw]\n"
278                 "       ipm     %[cc]\n"
279                 "       srl     %[cc],28\n"
280                 : [cc] "=&d" (ccode), [crw] "=Q" (*crw)
281                 :
282                 : "cc");
283         return ccode;
284 }
285
286 static inline int _stcrw(struct crw *crw)
287 {
288 #ifdef CONFIG_CIO_INJECT
289         if (static_branch_unlikely(&cio_inject_enabled)) {
290                 if (stcrw_get_injected(crw) == 0)
291                         return 0;
292         }
293 #endif
294
295         return __stcrw(crw);
296 }
297
298 int stcrw(struct crw *crw)
299 {
300         int ccode;
301
302         ccode = _stcrw(crw);
303         trace_s390_cio_stcrw(crw, ccode);
304
305         return ccode;
306 }