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