xref: /kvm-unit-tests/lib/s390x/css_lib.c (revision 610c15284a537484682adfb4b6d6313991ab954f)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Channel Subsystem tests library
4  *
5  * Copyright (c) 2020 IBM Corp
6  *
7  * Authors:
8  *  Pierre Morel <pmorel@linux.ibm.com>
9  */
10 #include <libcflat.h>
11 #include <alloc_phys.h>
12 #include <asm/page.h>
13 #include <string.h>
14 #include <interrupt.h>
15 #include <asm/arch_def.h>
16 #include <asm/time.h>
17 #include <asm/arch_def.h>
18 #include <alloc_page.h>
19 #include <malloc_io.h>
20 #include <css.h>
21 
22 struct schib schib;
23 struct chsc_scsc *chsc_scsc;
24 
25 static const char * const chsc_rsp_description[] = {
26 	"CHSC unknown error",
27 	"Command executed",
28 	"Invalid command",
29 	"Request-block error",
30 	"Command not installed",
31 	"Data not available",
32 	"Absolute address of channel-subsystem communication block exceeds 2G - 1.",
33 	"Invalid command format",
34 	"Invalid channel-subsystem identification (CSSID)",
35 	"The command-request block specified an invalid format for the command response block.",
36 	"Invalid subchannel-set identification (SSID)",
37 	"A busy condition precludes execution.",
38 };
39 
check_response(void * p)40 static bool check_response(void *p)
41 {
42 	struct chsc_header *h = p;
43 
44 	if (h->code == CHSC_RSP_OK)
45 		return true;
46 
47 	if (h->code > CHSC_RSP_MAX)
48 		h->code = 0;
49 
50 	report_abort("Response code %04x: %s", h->code,
51 		      chsc_rsp_description[h->code]);
52 	return false;
53 }
54 
chsc(void * p,uint16_t code,uint16_t len)55 bool chsc(void *p, uint16_t code, uint16_t len)
56 {
57 	struct chsc_header *h = p;
58 
59 	h->code = code;
60 	h->len = len;
61 
62 	switch (_chsc(p)) {
63 	case 3:
64 		report_abort("Subchannel invalid or not enabled.");
65 		break;
66 	case 2:
67 		report_abort("CHSC subchannel busy.");
68 		break;
69 	case 1:
70 		report_abort("Subchannel invalid or not enabled.");
71 		break;
72 	case 0:
73 		return check_response(p + len);
74 	}
75 	return false;
76 }
77 
get_chsc_scsc(void)78 bool get_chsc_scsc(void)
79 {
80 	int i, n;
81 	char buffer[510];
82 	char *p;
83 
84 	if (chsc_scsc) /* chsc_scsc already initialized */
85 		return true;
86 
87 	chsc_scsc = alloc_page();
88 	if (!chsc_scsc) {
89 		report_abort("could not allocate chsc_scsc page!");
90 		return false;
91 	}
92 
93 	if (!chsc(chsc_scsc, CHSC_SCSC, CHSC_SCSC_LEN))
94 		return false;
95 
96 	for (i = 0, p = buffer; i < CSS_GENERAL_FEAT_BITLEN; i++) {
97 		if (css_test_general_feature(i)) {
98 			n = snprintf(p, sizeof(buffer), "%d,", i);
99 			p += n;
100 		}
101 	}
102 	report_info("General features: %s", buffer);
103 
104 	for (i = 0, p = buffer; i < CSS_CHSC_FEAT_BITLEN; i++) {
105 		if (css_test_chsc_feature(i)) {
106 			n = snprintf(p, sizeof(buffer), "%d,", i);
107 			p += n;
108 		}
109 	}
110 	report_info("CHSC features: %s", buffer);
111 
112 	return true;
113 }
114 
115 /*
116  * css_enumerate:
117  * On success return the first subchannel ID found.
118  * On error return an invalid subchannel ID containing cc
119  */
css_enumerate(void)120 int css_enumerate(void)
121 {
122 	struct pmcw *pmcw = &schib.pmcw;
123 	int scn_found = 0;
124 	int dev_found = 0;
125 	int schid = 0;
126 	int cc;
127 	int scn;
128 
129 	for (scn = 0; scn < 0xffff; scn++) {
130 		cc = stsch(scn | SCHID_ONE, &schib);
131 		switch (cc) {
132 		case 0:		/* 0 means SCHIB stored */
133 			break;
134 		case 3:		/* 3 means no more channels */
135 			goto out;
136 		default:	/* 1 or 2 should never happen for STSCH */
137 			report_abort("Unexpected error %d on subchannel %08x",
138 				     cc, scn | SCHID_ONE);
139 			return cc;
140 		}
141 
142 		/* We currently only support type 0, a.k.a. I/O channels */
143 		if (PMCW_CHANNEL_TYPE(pmcw) != 0)
144 			continue;
145 
146 		/* We ignore I/O channels without valid devices */
147 		scn_found++;
148 		if (!(pmcw->flags & PMCW_DNV))
149 			continue;
150 
151 		/* We keep track of the first device as our test device */
152 		if (!schid)
153 			schid = scn | SCHID_ONE;
154 		report_info("Found subchannel %08x", scn | SCHID_ONE);
155 		dev_found++;
156 	}
157 
158 out:
159 	report_info("Tested subchannels: %d, I/O subchannels: %d, I/O devices: %d",
160 		    scn, scn_found, dev_found);
161 	return schid;
162 }
163 
164 /*
165  * css_enabled: report if the subchannel is enabled
166  * @schid: Subchannel Identifier
167  * Return value:
168  *   true if the subchannel is enabled
169  *   false otherwise
170  */
css_enabled(int schid)171 bool css_enabled(int schid)
172 {
173 	struct pmcw *pmcw = &schib.pmcw;
174 	int cc;
175 
176 	cc = stsch(schid, &schib);
177 	if (cc) {
178 		report_info("stsch: updating sch %08x failed with cc=%d",
179 			    schid, cc);
180 		return false;
181 	}
182 
183 	if (!(pmcw->flags & PMCW_ENABLE)) {
184 		report_info("stsch: sch %08x not enabled", schid);
185 		return false;
186 	}
187 	return true;
188 }
189 /*
190  * css_enable: enable the subchannel with the specified ISC
191  * @schid: Subchannel Identifier
192  * @isc  : number of the interruption subclass to use
193  * Return value:
194  *   On success: 0
195  *   On error the CC of the faulty instruction
196  *      or -1 if the retry count is exceeded.
197  */
css_enable(int schid,int isc)198 int css_enable(int schid, int isc)
199 {
200 	struct pmcw *pmcw = &schib.pmcw;
201 	int retry_count = 0;
202 	uint16_t flags;
203 	int cc;
204 
205 	/* Read the SCHIB for this subchannel */
206 	cc = stsch(schid, &schib);
207 	if (cc) {
208 		report_info("stsch: sch %08x failed with cc=%d", schid, cc);
209 		return cc;
210 	}
211 
212 	flags = PMCW_ENABLE | (isc << PMCW_ISC_SHIFT);
213 	if ((pmcw->flags & (PMCW_ISC_MASK | PMCW_ENABLE)) == flags) {
214 		report_info("stsch: sch %08x already enabled", schid);
215 		return 0;
216 	}
217 
218 retry:
219 	/* Update the SCHIB to enable the channel and set the ISC */
220 	pmcw->flags &= ~PMCW_ISC_MASK;
221 	pmcw->flags |= flags;
222 
223 	/* Tell the CSS we want to modify the subchannel */
224 	cc = msch(schid, &schib);
225 	if (cc) {
226 		/*
227 		 * If the subchannel is status pending or
228 		 * if a function is in progress,
229 		 * we consider both cases as errors.
230 		 */
231 		report_info("msch: sch %08x failed with cc=%d", schid, cc);
232 		return cc;
233 	}
234 
235 	/*
236 	 * Read the SCHIB again to verify the enablement
237 	 */
238 	if (css_enabled(schid))
239 		return 0;
240 
241 	if (retry_count++ < MAX_ENABLE_RETRIES) {
242 		mdelay(10); /* the hardware was not ready, give it some time */
243 		goto retry;
244 	}
245 
246 	report_info("msch: modifying sch %08x failed after %d retries. pmcw flags: %04x",
247 		    schid, retry_count, pmcw->flags);
248 	return -1;
249 }
250 
251 /*
252  * schib_update_mb: update the subchannel Measurement Block
253  * @schid: Subchannel Identifier
254  * @mb   : 64bit address of the measurement block
255  * @mbi : the measurement block offset
256  * @flags : PMCW_MBUE to enable measurement block update
257  *	    PMCW_DCTME to enable device connect time
258  *	    0 to disable measurement
259  * @format1: set if format 1 is to be used
260  */
schib_update_mb(int schid,uint64_t mb,uint16_t mbi,uint16_t flags,bool format1)261 static bool schib_update_mb(int schid, uint64_t mb, uint16_t mbi,
262 			    uint16_t flags, bool format1)
263 {
264 	struct pmcw *pmcw = &schib.pmcw;
265 	int cc;
266 
267 	/* Read the SCHIB for this subchannel */
268 	cc = stsch(schid, &schib);
269 	if (cc) {
270 		report_info("stsch: sch %08x failed with cc=%d", schid, cc);
271 		return false;
272 	}
273 
274 	/* Update the SCHIB to enable the measurement block */
275 	if (flags) {
276 		pmcw->flags |= flags;
277 
278 		if (format1)
279 			pmcw->flags2 |= PMCW_MBF1;
280 		else
281 			pmcw->flags2 &= ~PMCW_MBF1;
282 
283 		pmcw->mbi = mbi;
284 		schib.mbo = mb & ~0x3f;
285 	} else {
286 		pmcw->flags &= ~(PMCW_MBUE | PMCW_DCTME);
287 	}
288 
289 	/* Tell the CSS we want to modify the subchannel */
290 	cc = msch(schid, &schib);
291 	if (cc) {
292 		/*
293 		 * If the subchannel is status pending or
294 		 * if a function is in progress,
295 		 * we consider both cases as errors.
296 		 */
297 		report_info("msch: sch %08x failed with cc=%d", schid, cc);
298 		return false;
299 	}
300 
301 	/*
302 	 * Read the SCHIB again
303 	 */
304 	cc = stsch(schid, &schib);
305 	if (cc) {
306 		report_info("stsch: updating sch %08x failed with cc=%d",
307 			    schid, cc);
308 		return false;
309 	}
310 
311 	return true;
312 }
313 
314 /*
315  * css_enable_mb: enable the subchannel Measurement Block
316  * @schid: Subchannel Identifier
317  * @mb   : 64bit address of the measurement block
318  * @format1: set if format 1 is to be used
319  * @mbi : the measurement block offset
320  * @flags : PMCW_MBUE to enable measurement block update
321  *	    PMCW_DCTME to enable device connect time
322  */
css_enable_mb(int schid,uint64_t mb,uint16_t mbi,uint16_t flags,bool format1)323 bool css_enable_mb(int schid, uint64_t mb, uint16_t mbi, uint16_t flags,
324 		   bool format1)
325 {
326 	int retry_count = MAX_ENABLE_RETRIES;
327 	struct pmcw *pmcw = &schib.pmcw;
328 
329 	while (retry_count-- &&
330 	       !schib_update_mb(schid, mb, mbi, flags, format1))
331 		mdelay(10); /* the hardware was not ready, give it some time */
332 
333 	return schib.mbo == mb && pmcw->mbi == mbi;
334 }
335 
336 /*
337  * css_disable_mb: disable the subchannel Measurement Block
338  * @schid: Subchannel Identifier
339  */
css_disable_mb(int schid)340 bool css_disable_mb(int schid)
341 {
342 	int retry_count = MAX_ENABLE_RETRIES;
343 
344 	while (retry_count-- &&
345 	       !schib_update_mb(schid, 0, 0, 0, 0))
346 		mdelay(10); /* the hardware was not ready, give it some time */
347 
348 	return retry_count > 0;
349 }
350 
351 static struct irb irb;
352 
css_irq_io(void)353 void css_irq_io(void)
354 {
355 	int ret = 0;
356 	char *flags;
357 	int sid;
358 
359 	report_prefix_push("Interrupt");
360 	sid = lowcore.subsys_id_word;
361 	/* Lowlevel set the SID as interrupt parameter. */
362 	if (lowcore.io_int_param != sid) {
363 		report_fail("io_int_param: %x differs from subsys_id_word: %x",
364 			    lowcore.io_int_param, sid);
365 		goto pop;
366 	}
367 	report_prefix_pop();
368 
369 	report_prefix_push("tsch");
370 	ret = tsch(sid, &irb);
371 	switch (ret) {
372 	case 1:
373 		dump_irb(&irb);
374 		flags = dump_scsw_flags(irb.scsw.ctrl);
375 		report_fail("I/O interrupt, but tsch returns CC 1 for subchannel %08x.SCSW flags: %s",
376 			    sid, flags);
377 		break;
378 	case 2:
379 		report_fail("tsch returns unexpected CC 2");
380 		break;
381 	case 3:
382 		report_fail("tsch reporting sch %08x as not operational", sid);
383 		break;
384 	case 0:
385 		/* Stay humble on success */
386 		break;
387 	}
388 pop:
389 	report_prefix_pop();
390 	lowcore.io_old_psw.mask &= ~PSW_MASK_WAIT;
391 }
392 
start_ccw1_chain(unsigned int sid,struct ccw1 * ccw)393 int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw)
394 {
395 	struct orb orb = {
396 		.intparm = sid,
397 		.ctrl = ORB_CTRL_ISIC|ORB_CTRL_FMT|ORB_LPM_DFLT,
398 		.cpa = (unsigned int) (unsigned long)ccw,
399 	};
400 
401 	return ssch(sid, &orb);
402 }
403 
ccw_alloc(int code,void * data,int count,unsigned char flags)404 struct ccw1 *ccw_alloc(int code, void *data, int count, unsigned char flags)
405 {
406 	struct ccw1 *ccw;
407 
408 	ccw = alloc_io_mem(sizeof(*ccw), 0);
409 	if (!ccw)
410 		return NULL;
411 
412 	ccw->code = code;
413 	ccw->flags = flags;
414 	ccw->count = count;
415 	ccw->data_address = (int)(unsigned long)data;
416 
417 	return ccw;
418 }
419 
420 /* wait_and_check_io_completion:
421  * @schid: the subchannel ID
422  *
423  * Makes the most common check to validate a successful I/O
424  * completion.
425  * Only report failures.
426  */
wait_and_check_io_completion(int schid)427 int wait_and_check_io_completion(int schid)
428 {
429 	int ret = 0;
430 
431 	wait_for_interrupt(PSW_MASK_IO);
432 
433 	report_prefix_push("check I/O completion");
434 
435 	if (lowcore.io_int_param != schid) {
436 		report_fail("interrupt parameter: expected %08x got %08x",
437 			    schid, lowcore.io_int_param);
438 		ret = -1;
439 		goto end;
440 	}
441 
442 	/* Verify that device status is valid */
443 	if (!(irb.scsw.ctrl & SCSW_SC_PENDING)) {
444 		report_fail("No status pending after interrupt. Subch Ctrl: %08x",
445 			    irb.scsw.ctrl);
446 		ret = -1;
447 		goto end;
448 	}
449 
450 	if (!(irb.scsw.ctrl & (SCSW_SC_SECONDARY | SCSW_SC_PRIMARY))) {
451 		report_fail("Primary or secondary status missing. Subch Ctrl: %08x",
452 			    irb.scsw.ctrl);
453 		ret = -1;
454 		goto end;
455 	}
456 
457 	if (!(irb.scsw.dev_stat & (SCSW_DEVS_DEV_END | SCSW_DEVS_SCH_END))) {
458 		report_fail("No device end or sch end. Dev. status: %02x",
459 			    irb.scsw.dev_stat);
460 		ret = -1;
461 		goto end;
462 	}
463 
464 	if (irb.scsw.sch_stat & ~SCSW_SCHS_IL) {
465 		report_info("Unexpected Subch. status %02x", irb.scsw.sch_stat);
466 		ret = -1;
467 		goto end;
468 	}
469 
470 end:
471 	report_prefix_pop();
472 	return ret;
473 }
474 
475 /*
476  * css_residual_count
477  * Return the residual count, if it is valid.
478  *
479  * Return value:
480  * Success: the residual count
481  * Not meaningful: -1 (-1 can not be a valid count)
482  */
css_residual_count(unsigned int schid)483 int css_residual_count(unsigned int schid)
484 {
485 
486 	if (!(irb.scsw.ctrl & (SCSW_SC_PENDING | SCSW_SC_PRIMARY)))
487 		return -1;
488 
489 	if (irb.scsw.dev_stat)
490 		if (irb.scsw.sch_stat & ~(SCSW_SCHS_PCI | SCSW_SCHS_IL))
491 			return -1;
492 
493 	return irb.scsw.count;
494 }
495 
496 /*
497  * enable_io_isc: setup ISC in Control Register 6
498  * @isc: The interruption Sub Class as a bitfield
499  */
enable_io_isc(uint8_t isc)500 void enable_io_isc(uint8_t isc)
501 {
502 	uint64_t value;
503 
504 	value = (uint64_t)isc << 24;
505 	lctlg(6, value);
506 }
507 
is_path_installed(struct schib * schib,int chp_idx)508 static int is_path_installed(struct schib *schib, int chp_idx)
509 {
510 	return schib->pmcw.pim & BIT(7 - chp_idx);
511 }
512 
513 /*
514  * css_find_installed_chpid: find any installed CHPID
515  * @sid: subsystem-identification word
516  * @chpid_out: store the found chpid here, left alone if none found
517  *
518  * returns 0 on success, -1 if no chpid found any other value
519  * indicates the condition code of a failing STSCH instruction
520  */
css_find_installed_chpid(int sid,uint8_t * chpid_out)521 int css_find_installed_chpid(int sid, uint8_t *chpid_out)
522 {
523 	int cc;
524 
525 	cc = stsch(sid, &schib);
526 	if (cc) {
527 		report_fail("%s: sch %08x failed with cc=%d", __func__, sid, cc);
528 		return cc;
529 	}
530 
531 	for (int i = 0; i < ARRAY_SIZE(schib.pmcw.chpid); i++) {
532 		if (is_path_installed(&schib, i)) {
533 			*chpid_out = schib.pmcw.chpid[i];
534 			return 0;
535 		}
536 	}
537 
538 	return -1;
539 }
540 
541 /*
542  * css_generate_crw: Generate a CRW by issuing RCHP on any channel path
543  * @sid: subsystem-identification word
544  *
545  * returns 0 when a CRW was generated, -1 if no chpid found.
546  */
css_generate_crw(int sid)547 int css_generate_crw(int sid)
548 {
549 	int ret, cc;
550 	uint8_t chpid;
551 
552 	report_prefix_push("Generate CRW");
553 
554 	ret = css_find_installed_chpid(sid, &chpid);
555 	if (ret) {
556 		report_fail("No CHPID found: ret=%d", ret);
557 		return -1;
558 	}
559 
560 	cc = rchp(chpid);
561 	report(!cc, "rhcp cc != 0");
562 
563 	report_prefix_pop();
564 
565 	return 0;
566 }
567