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