xref: /kvm-unit-tests/lib/s390x/css.h (revision 7fbcef02aaef9797724b818898bca662293cfff8)
16c9f99dfSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
2a3b101f0SPierre Morel /*
3a3b101f0SPierre Morel  * CSS definitions
4a3b101f0SPierre Morel  *
5a3b101f0SPierre Morel  * Copyright IBM, Corp. 2020
6a3b101f0SPierre Morel  * Author: Pierre Morel <pmorel@linux.ibm.com>
7a3b101f0SPierre Morel  */
8a3b101f0SPierre Morel 
9a3b101f0SPierre Morel #ifndef CSS_H
10a3b101f0SPierre Morel #define CSS_H
11a3b101f0SPierre Morel 
128cb729e4SPierre Morel #define lowcore_ptr ((struct lowcore *)0x0)
138cb729e4SPierre Morel 
14a3b101f0SPierre Morel /* subchannel ID bit 16 must always be one */
15a3b101f0SPierre Morel #define SCHID_ONE	0x00010000
16a3b101f0SPierre Morel 
17a3b101f0SPierre Morel #define CCW_F_CD	0x80
18a3b101f0SPierre Morel #define CCW_F_CC	0x40
19a3b101f0SPierre Morel #define CCW_F_SLI	0x20
20a3b101f0SPierre Morel #define CCW_F_SKP	0x10
21a3b101f0SPierre Morel #define CCW_F_PCI	0x08
22a3b101f0SPierre Morel #define CCW_F_IDA	0x04
23a3b101f0SPierre Morel #define CCW_F_S		0x02
24a3b101f0SPierre Morel #define CCW_F_MIDA	0x01
25a3b101f0SPierre Morel 
26a3b101f0SPierre Morel #define CCW_C_NOP	0x03
27a3b101f0SPierre Morel #define CCW_C_TIC	0x08
28a3b101f0SPierre Morel 
29a3b101f0SPierre Morel struct ccw1 {
30a3b101f0SPierre Morel 	uint8_t code;
31a3b101f0SPierre Morel 	uint8_t flags;
32a3b101f0SPierre Morel 	uint16_t count;
33a3b101f0SPierre Morel 	uint32_t data_address;
34a3b101f0SPierre Morel } __attribute__ ((aligned(8)));
35a3b101f0SPierre Morel 
36a3b101f0SPierre Morel #define ORB_CTRL_KEY	0xf0000000
37a3b101f0SPierre Morel #define ORB_CTRL_SPND	0x08000000
38a3b101f0SPierre Morel #define ORB_CTRL_STR	0x04000000
39a3b101f0SPierre Morel #define ORB_CTRL_MOD	0x02000000
40a3b101f0SPierre Morel #define ORB_CTRL_SYNC	0x01000000
41a3b101f0SPierre Morel #define ORB_CTRL_FMT	0x00800000
42a3b101f0SPierre Morel #define ORB_CTRL_PFCH	0x00400000
43a3b101f0SPierre Morel #define ORB_CTRL_ISIC	0x00200000
44a3b101f0SPierre Morel #define ORB_CTRL_ALCC	0x00100000
45a3b101f0SPierre Morel #define ORB_CTRL_SSIC	0x00080000
46a3b101f0SPierre Morel #define ORB_CTRL_CPTC	0x00040000
47a3b101f0SPierre Morel #define ORB_CTRL_C64	0x00020000
48a3b101f0SPierre Morel #define ORB_CTRL_I2K	0x00010000
49a3b101f0SPierre Morel #define ORB_CTRL_LPM	0x0000ff00
50a3b101f0SPierre Morel #define ORB_CTRL_ILS	0x00000080
51a3b101f0SPierre Morel #define ORB_CTRL_MIDAW	0x00000040
52a3b101f0SPierre Morel #define ORB_CTRL_ORBX	0x00000001
53a3b101f0SPierre Morel 
54a3b101f0SPierre Morel #define ORB_LPM_DFLT	0x00008000
55a3b101f0SPierre Morel 
56a3b101f0SPierre Morel struct orb {
57a3b101f0SPierre Morel 	uint32_t intparm;
58a3b101f0SPierre Morel 	uint32_t ctrl;
59a3b101f0SPierre Morel 	uint32_t cpa;
60a3b101f0SPierre Morel 	uint32_t prio;
61a3b101f0SPierre Morel 	uint32_t reserved[4];
62a3b101f0SPierre Morel } __attribute__ ((aligned(4)));
63a3b101f0SPierre Morel 
64a3b101f0SPierre Morel struct scsw {
658cb729e4SPierre Morel #define SCSW_SC_PENDING		0x00000001
668cb729e4SPierre Morel #define SCSW_SC_SECONDARY	0x00000002
678cb729e4SPierre Morel #define SCSW_SC_PRIMARY		0x00000004
688cb729e4SPierre Morel #define SCSW_SC_INTERMEDIATE	0x00000008
698cb729e4SPierre Morel #define SCSW_SC_ALERT		0x00000010
70a3b101f0SPierre Morel 	uint32_t ctrl;
71a3b101f0SPierre Morel 	uint32_t ccw_addr;
728cb729e4SPierre Morel #define SCSW_DEVS_DEV_END	0x04
738cb729e4SPierre Morel #define SCSW_DEVS_SCH_END	0x08
74a3b101f0SPierre Morel 	uint8_t  dev_stat;
758cb729e4SPierre Morel #define SCSW_SCHS_PCI	0x80
768cb729e4SPierre Morel #define SCSW_SCHS_IL	0x40
77a3b101f0SPierre Morel 	uint8_t  sch_stat;
78a3b101f0SPierre Morel 	uint16_t count;
79a3b101f0SPierre Morel };
80a3b101f0SPierre Morel 
81a3b101f0SPierre Morel struct pmcw {
82a3b101f0SPierre Morel 	uint32_t intparm;
83a3b101f0SPierre Morel #define PMCW_DNV	0x0001
84a3b101f0SPierre Morel #define PMCW_ENABLE	0x0080
85551e6622SPierre Morel #define PMCW_ISC_MASK	0x3800
86551e6622SPierre Morel #define PMCW_ISC_SHIFT	11
87a3b101f0SPierre Morel 	uint16_t flags;
88a3b101f0SPierre Morel 	uint16_t devnum;
89a3b101f0SPierre Morel 	uint8_t  lpm;
90a3b101f0SPierre Morel 	uint8_t  pnom;
91a3b101f0SPierre Morel 	uint8_t  lpum;
92a3b101f0SPierre Morel 	uint8_t  pim;
93a3b101f0SPierre Morel 	uint16_t mbi;
94a3b101f0SPierre Morel 	uint8_t  pom;
95a3b101f0SPierre Morel 	uint8_t  pam;
96a3b101f0SPierre Morel 	uint8_t  chpid[8];
97a3b101f0SPierre Morel 	uint32_t flags2;
98a3b101f0SPierre Morel };
99a3b101f0SPierre Morel #define PMCW_CHANNEL_TYPE(pmcw) (pmcw->flags2 >> 21)
100a3b101f0SPierre Morel 
101a3b101f0SPierre Morel struct schib {
102a3b101f0SPierre Morel 	struct pmcw pmcw;
103a3b101f0SPierre Morel 	struct scsw scsw;
104a3b101f0SPierre Morel 	uint8_t  md[12];
105a3b101f0SPierre Morel } __attribute__ ((aligned(4)));
106a3b101f0SPierre Morel 
107a3b101f0SPierre Morel struct irb {
108a3b101f0SPierre Morel 	struct scsw scsw;
109a3b101f0SPierre Morel 	uint32_t esw[5];
110a3b101f0SPierre Morel 	uint32_t ecw[8];
111a3b101f0SPierre Morel 	uint32_t emw[8];
112a3b101f0SPierre Morel } __attribute__ ((aligned(4)));
113a3b101f0SPierre Morel 
1148cb729e4SPierre Morel #define CCW_CMD_SENSE_ID	0xe4
1158cb729e4SPierre Morel #define CSS_SENSEID_COMMON_LEN	8
1168cb729e4SPierre Morel struct senseid {
1178cb729e4SPierre Morel 	/* common part */
1188cb729e4SPierre Morel 	uint8_t reserved;        /* always 0x'FF' */
1198cb729e4SPierre Morel 	uint16_t cu_type;        /* control unit type */
1208cb729e4SPierre Morel 	uint8_t cu_model;        /* control unit model */
1218cb729e4SPierre Morel 	uint16_t dev_type;       /* device type */
1228cb729e4SPierre Morel 	uint8_t dev_model;       /* device model */
1238cb729e4SPierre Morel 	uint8_t unused;          /* padding byte */
1248cb729e4SPierre Morel 	uint8_t padding[256 - 8]; /* Extended part */
1258cb729e4SPierre Morel } __attribute__ ((aligned(4))) __attribute__ ((packed));
1268cb729e4SPierre Morel 
127a3b101f0SPierre Morel /* CSS low level access functions */
128a3b101f0SPierre Morel 
129a3b101f0SPierre Morel static inline int ssch(unsigned long schid, struct orb *addr)
130a3b101f0SPierre Morel {
131a3b101f0SPierre Morel 	register long long reg1 asm("1") = schid;
132a3b101f0SPierre Morel 	int cc;
133a3b101f0SPierre Morel 
134a3b101f0SPierre Morel 	asm volatile(
135a3b101f0SPierre Morel 		"	ssch	0(%2)\n"
136a3b101f0SPierre Morel 		"	ipm	%0\n"
137a3b101f0SPierre Morel 		"	srl	%0,28\n"
138a3b101f0SPierre Morel 		: "=d" (cc)
139a3b101f0SPierre Morel 		: "d" (reg1), "a" (addr), "m" (*addr)
140a3b101f0SPierre Morel 		: "cc", "memory");
141a3b101f0SPierre Morel 	return cc;
142a3b101f0SPierre Morel }
143a3b101f0SPierre Morel 
144a3b101f0SPierre Morel static inline int stsch(unsigned long schid, struct schib *addr)
145a3b101f0SPierre Morel {
146a3b101f0SPierre Morel 	register unsigned long reg1 asm ("1") = schid;
147a3b101f0SPierre Morel 	int cc;
148a3b101f0SPierre Morel 
149a3b101f0SPierre Morel 	asm volatile(
150a3b101f0SPierre Morel 		"	stsch	0(%3)\n"
151a3b101f0SPierre Morel 		"	ipm	%0\n"
152a3b101f0SPierre Morel 		"	srl	%0,28"
153a3b101f0SPierre Morel 		: "=d" (cc), "=m" (*addr)
154a3b101f0SPierre Morel 		: "d" (reg1), "a" (addr)
155a3b101f0SPierre Morel 		: "cc");
156a3b101f0SPierre Morel 	return cc;
157a3b101f0SPierre Morel }
158a3b101f0SPierre Morel 
159a3b101f0SPierre Morel static inline int msch(unsigned long schid, struct schib *addr)
160a3b101f0SPierre Morel {
161a3b101f0SPierre Morel 	register unsigned long reg1 asm ("1") = schid;
162a3b101f0SPierre Morel 	int cc;
163a3b101f0SPierre Morel 
164a3b101f0SPierre Morel 	asm volatile(
165a3b101f0SPierre Morel 		"	msch	0(%3)\n"
166a3b101f0SPierre Morel 		"	ipm	%0\n"
167a3b101f0SPierre Morel 		"	srl	%0,28"
168a3b101f0SPierre Morel 		: "=d" (cc)
169a3b101f0SPierre Morel 		: "d" (reg1), "m" (*addr), "a" (addr)
170a3b101f0SPierre Morel 		: "cc");
171a3b101f0SPierre Morel 	return cc;
172a3b101f0SPierre Morel }
173a3b101f0SPierre Morel 
174a3b101f0SPierre Morel static inline int tsch(unsigned long schid, struct irb *addr)
175a3b101f0SPierre Morel {
176a3b101f0SPierre Morel 	register unsigned long reg1 asm ("1") = schid;
177a3b101f0SPierre Morel 	int cc;
178a3b101f0SPierre Morel 
179a3b101f0SPierre Morel 	asm volatile(
180a3b101f0SPierre Morel 		"	tsch	0(%3)\n"
181a3b101f0SPierre Morel 		"	ipm	%0\n"
182a3b101f0SPierre Morel 		"	srl	%0,28"
183a3b101f0SPierre Morel 		: "=d" (cc), "=m" (*addr)
184a3b101f0SPierre Morel 		: "d" (reg1), "a" (addr)
185a3b101f0SPierre Morel 		: "cc");
186a3b101f0SPierre Morel 	return cc;
187a3b101f0SPierre Morel }
188a3b101f0SPierre Morel 
189a3b101f0SPierre Morel static inline int hsch(unsigned long schid)
190a3b101f0SPierre Morel {
191a3b101f0SPierre Morel 	register unsigned long reg1 asm("1") = schid;
192a3b101f0SPierre Morel 	int cc;
193a3b101f0SPierre Morel 
194a3b101f0SPierre Morel 	asm volatile(
195a3b101f0SPierre Morel 		"	hsch\n"
196a3b101f0SPierre Morel 		"	ipm	%0\n"
197a3b101f0SPierre Morel 		"	srl	%0,28"
198a3b101f0SPierre Morel 		: "=d" (cc)
199a3b101f0SPierre Morel 		: "d" (reg1)
200a3b101f0SPierre Morel 		: "cc");
201a3b101f0SPierre Morel 	return cc;
202a3b101f0SPierre Morel }
203a3b101f0SPierre Morel 
204a3b101f0SPierre Morel static inline int xsch(unsigned long schid)
205a3b101f0SPierre Morel {
206a3b101f0SPierre Morel 	register unsigned long reg1 asm("1") = schid;
207a3b101f0SPierre Morel 	int cc;
208a3b101f0SPierre Morel 
209a3b101f0SPierre Morel 	asm volatile(
210a3b101f0SPierre Morel 		"	xsch\n"
211a3b101f0SPierre Morel 		"	ipm	%0\n"
212a3b101f0SPierre Morel 		"	srl	%0,28"
213a3b101f0SPierre Morel 		: "=d" (cc)
214a3b101f0SPierre Morel 		: "d" (reg1)
215a3b101f0SPierre Morel 		: "cc");
216a3b101f0SPierre Morel 	return cc;
217a3b101f0SPierre Morel }
218a3b101f0SPierre Morel 
219a3b101f0SPierre Morel static inline int csch(unsigned long schid)
220a3b101f0SPierre Morel {
221a3b101f0SPierre Morel 	register unsigned long reg1 asm("1") = schid;
222a3b101f0SPierre Morel 	int cc;
223a3b101f0SPierre Morel 
224a3b101f0SPierre Morel 	asm volatile(
225a3b101f0SPierre Morel 		"	csch\n"
226a3b101f0SPierre Morel 		"	ipm	%0\n"
227a3b101f0SPierre Morel 		"	srl	%0,28"
228a3b101f0SPierre Morel 		: "=d" (cc)
229a3b101f0SPierre Morel 		: "d" (reg1)
230a3b101f0SPierre Morel 		: "cc");
231a3b101f0SPierre Morel 	return cc;
232a3b101f0SPierre Morel }
233a3b101f0SPierre Morel 
234a3b101f0SPierre Morel static inline int rsch(unsigned long schid)
235a3b101f0SPierre Morel {
236a3b101f0SPierre Morel 	register unsigned long reg1 asm("1") = schid;
237a3b101f0SPierre Morel 	int cc;
238a3b101f0SPierre Morel 
239a3b101f0SPierre Morel 	asm volatile(
240a3b101f0SPierre Morel 		"	rsch\n"
241a3b101f0SPierre Morel 		"	ipm	%0\n"
242a3b101f0SPierre Morel 		"	srl	%0,28"
243a3b101f0SPierre Morel 		: "=d" (cc)
244a3b101f0SPierre Morel 		: "d" (reg1)
245a3b101f0SPierre Morel 		: "cc");
246a3b101f0SPierre Morel 	return cc;
247a3b101f0SPierre Morel }
248a3b101f0SPierre Morel 
249a3b101f0SPierre Morel static inline int rchp(unsigned long chpid)
250a3b101f0SPierre Morel {
251a3b101f0SPierre Morel 	register unsigned long reg1 asm("1") = chpid;
252a3b101f0SPierre Morel 	int cc;
253a3b101f0SPierre Morel 
254a3b101f0SPierre Morel 	asm volatile(
255a3b101f0SPierre Morel 		"	rchp\n"
256a3b101f0SPierre Morel 		"	ipm	%0\n"
257a3b101f0SPierre Morel 		"	srl	%0,28"
258a3b101f0SPierre Morel 		: "=d" (cc)
259a3b101f0SPierre Morel 		: "d" (reg1)
260a3b101f0SPierre Morel 		: "cc");
261a3b101f0SPierre Morel 	return cc;
262a3b101f0SPierre Morel }
263a3b101f0SPierre Morel 
264a3b101f0SPierre Morel /* Debug functions */
265a3b101f0SPierre Morel char *dump_pmcw_flags(uint16_t f);
266a3b101f0SPierre Morel char *dump_scsw_flags(uint32_t f);
267a3b101f0SPierre Morel 
268a3b101f0SPierre Morel void dump_scsw(struct scsw *scsw);
269a3b101f0SPierre Morel void dump_irb(struct irb *irbp);
270a3b101f0SPierre Morel void dump_schib(struct schib *sch);
271a3b101f0SPierre Morel struct ccw1 *dump_ccw(struct ccw1 *cp);
272a3b101f0SPierre Morel void dump_irb(struct irb *irbp);
273a3b101f0SPierre Morel void dump_pmcw(struct pmcw *p);
274a3b101f0SPierre Morel void dump_orb(struct orb *op);
275a3b101f0SPierre Morel 
276a3b101f0SPierre Morel int css_enumerate(void);
277a3b101f0SPierre Morel #define MAX_ENABLE_RETRIES      5
278a3b101f0SPierre Morel 
279551e6622SPierre Morel #define IO_SCH_ISC      3
280551e6622SPierre Morel int css_enable(int schid, int isc);
2818cb729e4SPierre Morel 
2828cb729e4SPierre Morel /* Library functions */
2838cb729e4SPierre Morel int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw);
284a6e5e596SPierre Morel struct ccw1 *ccw_alloc(int code, void *data, int count, unsigned char flags);
2858cb729e4SPierre Morel void css_irq_io(void);
2868cb729e4SPierre Morel int css_residual_count(unsigned int schid);
2878cb729e4SPierre Morel 
2888cb729e4SPierre Morel void enable_io_isc(uint8_t isc);
2898cb729e4SPierre Morel int wait_and_check_io_completion(int schid);
2908cb729e4SPierre Morel 
291*7fbcef02SPierre Morel /*
292*7fbcef02SPierre Morel  * CHSC definitions
293*7fbcef02SPierre Morel  */
294*7fbcef02SPierre Morel struct chsc_header {
295*7fbcef02SPierre Morel 	uint16_t len;
296*7fbcef02SPierre Morel 	uint16_t code;
297*7fbcef02SPierre Morel };
298*7fbcef02SPierre Morel 
299*7fbcef02SPierre Morel /* Store Channel Subsystem Characteristics */
300*7fbcef02SPierre Morel struct chsc_scsc {
301*7fbcef02SPierre Morel 	struct chsc_header req;
302*7fbcef02SPierre Morel 	uint16_t req_fmt;
303*7fbcef02SPierre Morel 	uint8_t cssid;
304*7fbcef02SPierre Morel 	uint8_t reserved[9];
305*7fbcef02SPierre Morel 	struct chsc_header res;
306*7fbcef02SPierre Morel 	uint32_t res_fmt;
307*7fbcef02SPierre Morel 	uint64_t general_char[255];
308*7fbcef02SPierre Morel 	uint64_t chsc_char[254];
309*7fbcef02SPierre Morel };
310*7fbcef02SPierre Morel 
311*7fbcef02SPierre Morel extern struct chsc_scsc *chsc_scsc;
312*7fbcef02SPierre Morel #define CHSC_SCSC	0x0010
313*7fbcef02SPierre Morel #define CHSC_SCSC_LEN	0x0010
314*7fbcef02SPierre Morel 
315*7fbcef02SPierre Morel bool get_chsc_scsc(void);
316*7fbcef02SPierre Morel 
317*7fbcef02SPierre Morel #define CSS_GENERAL_FEAT_BITLEN	(255 * 64)
318*7fbcef02SPierre Morel #define CSS_CHSC_FEAT_BITLEN	(254 * 64)
319*7fbcef02SPierre Morel 
320*7fbcef02SPierre Morel #define CHSC_SCSC	0x0010
321*7fbcef02SPierre Morel #define CHSC_SCSC_LEN	0x0010
322*7fbcef02SPierre Morel 
323*7fbcef02SPierre Morel #define CHSC_ERROR	0x0000
324*7fbcef02SPierre Morel #define CHSC_RSP_OK	0x0001
325*7fbcef02SPierre Morel #define CHSC_RSP_INVAL	0x0002
326*7fbcef02SPierre Morel #define CHSC_RSP_REQERR	0x0003
327*7fbcef02SPierre Morel #define CHSC_RSP_ENOCMD	0x0004
328*7fbcef02SPierre Morel #define CHSC_RSP_NODATA	0x0005
329*7fbcef02SPierre Morel #define CHSC_RSP_SUP31B	0x0006
330*7fbcef02SPierre Morel #define CHSC_RSP_EFRMT	0x0007
331*7fbcef02SPierre Morel #define CHSC_RSP_ECSSID	0x0008
332*7fbcef02SPierre Morel #define CHSC_RSP_ERFRMT	0x0009
333*7fbcef02SPierre Morel #define CHSC_RSP_ESSID	0x000A
334*7fbcef02SPierre Morel #define CHSC_RSP_EBUSY	0x000B
335*7fbcef02SPierre Morel #define CHSC_RSP_MAX	0x000B
336*7fbcef02SPierre Morel 
337*7fbcef02SPierre Morel static inline int _chsc(void *p)
338*7fbcef02SPierre Morel {
339*7fbcef02SPierre Morel 	int cc;
340*7fbcef02SPierre Morel 
341*7fbcef02SPierre Morel 	asm volatile(" .insn   rre,0xb25f0000,%2,0\n"
342*7fbcef02SPierre Morel 		     " ipm     %0\n"
343*7fbcef02SPierre Morel 		     " srl     %0,28\n"
344*7fbcef02SPierre Morel 		     : "=d" (cc), "=m" (p)
345*7fbcef02SPierre Morel 		     : "d" (p), "m" (p)
346*7fbcef02SPierre Morel 		     : "cc");
347*7fbcef02SPierre Morel 
348*7fbcef02SPierre Morel 	return cc;
349*7fbcef02SPierre Morel }
350*7fbcef02SPierre Morel 
351*7fbcef02SPierre Morel bool chsc(void *p, uint16_t code, uint16_t len);
352*7fbcef02SPierre Morel 
353*7fbcef02SPierre Morel #include <bitops.h>
354*7fbcef02SPierre Morel #define css_test_general_feature(bit) test_bit_inv(bit, chsc_scsc->general_char)
355*7fbcef02SPierre Morel #define css_test_chsc_feature(bit) test_bit_inv(bit, chsc_scsc->chsc_char)
356*7fbcef02SPierre Morel 
357a3b101f0SPierre Morel #endif
358