File Index
Files and directories
Sign in
FILE

ioasm.c

File preview with syntax highlighting.

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