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