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
__stsch(struct subchannel_id schid,struct schib * addr)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
stsch(struct subchannel_id schid,struct schib * addr)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
__msch(struct subchannel_id schid,struct schib * addr)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
msch(struct subchannel_id schid,struct schib * addr)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
__tsch(struct subchannel_id schid,struct irb * addr)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
tsch(struct subchannel_id schid,struct irb * addr)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
__ssch(struct subchannel_id schid,union orb * addr)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
ssch(struct subchannel_id schid,union orb * addr)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
__csch(struct subchannel_id schid)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
csch(struct subchannel_id schid)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
tpi(struct tpi_info * addr)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
chsc(void * chsc_area)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
__rsch(struct subchannel_id schid)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
rsch(struct subchannel_id schid)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
__hsch(struct subchannel_id schid)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
hsch(struct subchannel_id schid)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
__xsch(struct subchannel_id schid)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
xsch(struct subchannel_id schid)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
__stcrw(struct crw * crw)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
_stcrw(struct crw * crw)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
stcrw(struct crw * crw)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 }
307