xref: /kvm-unit-tests/s390x/css.c (revision 7502d215c68346c321ba356e809a98dd37df5cdf)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Channel Subsystem tests
4  *
5  * Copyright (c) 2020 IBM Corp
6  *
7  * Authors:
8  *  Pierre Morel <pmorel@linux.ibm.com>
9  */
10 
11 #include <libcflat.h>
12 #include <alloc_phys.h>
13 #include <asm/page.h>
14 #include <string.h>
15 #include <interrupt.h>
16 #include <asm/arch_def.h>
17 #include <alloc_page.h>
18 
19 #include <malloc_io.h>
20 #include <css.h>
21 #include <asm/barrier.h>
22 
23 #define DEFAULT_CU_TYPE		0x3832 /* virtio-ccw */
24 static unsigned long cu_type = DEFAULT_CU_TYPE;
25 
26 static int test_device_sid;
27 static struct senseid *senseid;
28 struct ccw1 *ccw;
29 
30 char alignment_test_page[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
31 
32 static void test_enumerate(void)
33 {
34 	test_device_sid = css_enumerate();
35 	if (test_device_sid & SCHID_ONE) {
36 		report_pass("Schid of first I/O device: 0x%08x", test_device_sid);
37 		return;
38 	}
39 	report_fail("No I/O device found");
40 }
41 
42 static void test_enable(void)
43 {
44 	int cc;
45 
46 	if (!test_device_sid) {
47 		report_skip("No device");
48 		return;
49 	}
50 
51 	cc = css_enable(test_device_sid, IO_SCH_ISC);
52 
53 	report(cc == 0, "Enable subchannel %08x", test_device_sid);
54 }
55 
56 /*
57  * test_sense
58  * Pre-requisites:
59  * - We need the test device as the first recognized
60  *   device by the enumeration.
61  */
62 static void test_sense(void)
63 {
64 	int ret;
65 	int len;
66 
67 	if (!test_device_sid) {
68 		report_skip("No device");
69 		return;
70 	}
71 
72 	ret = css_enable(test_device_sid, IO_SCH_ISC);
73 	if (ret) {
74 		report_fail("Could not enable the subchannel: %08x",
75 			    test_device_sid);
76 		return;
77 	}
78 
79 	lowcore_ptr->io_int_param = 0;
80 
81 	senseid = alloc_io_mem(sizeof(*senseid), 0);
82 	if (!senseid) {
83 		report_fail("Allocation of senseid");
84 		return;
85 	}
86 
87 	ccw = ccw_alloc(CCW_CMD_SENSE_ID, senseid, sizeof(*senseid), CCW_F_SLI);
88 	if (!ccw) {
89 		report_fail("Allocation of CCW");
90 		goto error_ccw;
91 	}
92 
93 	ret = start_ccw1_chain(test_device_sid, ccw);
94 	if (ret) {
95 		report_fail("Starting CCW chain");
96 		goto error;
97 	}
98 
99 	if (wait_and_check_io_completion(test_device_sid) < 0)
100 		goto error;
101 
102 	/* Test transfer completion */
103 	report_prefix_push("ssch transfer completion");
104 
105 	ret = css_residual_count(test_device_sid);
106 
107 	if (ret < 0) {
108 		report_info("no valid residual count");
109 	} else if (ret != 0) {
110 		len = sizeof(*senseid) - ret;
111 		if (ret && len < CSS_SENSEID_COMMON_LEN) {
112 			report_fail("transferred a too short length: %d", ret);
113 			goto error;
114 		} else if (ret && len)
115 			report_info("transferred a shorter length: %d", len);
116 	}
117 
118 	if (senseid->reserved != 0xff) {
119 		report_fail("transferred garbage: 0x%02x", senseid->reserved);
120 		goto error;
121 	}
122 
123 	report_prefix_pop();
124 
125 	report_info("reserved 0x%02x cu_type 0x%04x cu_model 0x%02x dev_type 0x%04x dev_model 0x%02x",
126 		    senseid->reserved, senseid->cu_type, senseid->cu_model,
127 		    senseid->dev_type, senseid->dev_model);
128 
129 	report(senseid->cu_type == cu_type, "cu_type expected 0x%04x got 0x%04x",
130 	       (uint16_t)cu_type, senseid->cu_type);
131 
132 error:
133 	free_io_mem(ccw, sizeof(*ccw));
134 error_ccw:
135 	free_io_mem(senseid, sizeof(*senseid));
136 }
137 
138 static void sense_id(void)
139 {
140 	assert(!start_ccw1_chain(test_device_sid, ccw));
141 
142 	assert(wait_and_check_io_completion(test_device_sid) >= 0);
143 }
144 
145 static void css_init(void)
146 {
147 	assert(register_io_int_func(css_irq_io) == 0);
148 	lowcore_ptr->io_int_param = 0;
149 
150 	report(get_chsc_scsc(), "Store Channel Characteristics");
151 }
152 
153 static void test_schm(void)
154 {
155 	if (css_test_general_feature(CSSC_EXTENDED_MEASUREMENT_BLOCK))
156 		report_info("Extended measurement block available");
157 
158 	/* bits 59-63 of MB address must be 0  if MBU is defined */
159 	report_prefix_push("Unaligned operand");
160 	expect_pgm_int();
161 	schm((void *)0x01, SCHM_MBU);
162 	check_pgm_int_code(PGM_INT_CODE_OPERAND);
163 	report_prefix_pop();
164 
165 	/* bits 36-61 of register 1 (flags) must be 0 */
166 	report_prefix_push("Bad flags");
167 	expect_pgm_int();
168 	schm(NULL, 0xfffffffc);
169 	check_pgm_int_code(PGM_INT_CODE_OPERAND);
170 	report_prefix_pop();
171 
172 	/* SCHM is a privilege operation */
173 	report_prefix_push("Privilege");
174 	enter_pstate();
175 	expect_pgm_int();
176 	schm(NULL, SCHM_MBU);
177 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
178 	report_prefix_pop();
179 
180 	/* Normal operation */
181 	report_prefix_push("Normal operation");
182 	schm(NULL, SCHM_MBU);
183 	report_pass("SCHM call without address");
184 	report_prefix_pop();
185 }
186 
187 #define SCHM_UPDATE_CNT 10
188 static bool start_measuring(uint64_t mbo, uint16_t mbi, bool fmt1)
189 {
190 	int i;
191 
192 	senseid = alloc_io_mem(sizeof(*senseid), 0);
193 	assert(senseid);
194 
195 	ccw = ccw_alloc(CCW_CMD_SENSE_ID, senseid, sizeof(*senseid), CCW_F_SLI);
196 	assert(ccw);
197 
198 	if (!css_enable_mb(test_device_sid, mbo, mbi, PMCW_MBUE, fmt1)) {
199 		report_abort("Enabling measurement block failed");
200 		return false;
201 	}
202 
203 	for (i = 0; i < SCHM_UPDATE_CNT; i++)
204 		sense_id();
205 
206 	free_io_mem(ccw, sizeof(*ccw));
207 	free_io_mem(senseid, sizeof(*senseid));
208 
209 	return true;
210 }
211 
212 /*
213  * test_schm_fmt0:
214  * With measurement block format 0 a memory space is shared
215  * by all subchannels, each subchannel can provide an index
216  * for the measurement block facility to store the measurements.
217  */
218 static void test_schm_fmt0(void)
219 {
220 	struct measurement_block_format0 *mb0;
221 	int shared_mb_size = 2 * sizeof(struct measurement_block_format0);
222 
223 	if (!test_device_sid) {
224 		report_skip("No device");
225 		return;
226 	}
227 
228 	/* Allocate zeroed Measurement block */
229 	mb0 = alloc_io_mem(shared_mb_size, 0);
230 	if (!mb0) {
231 		report_abort("measurement_block_format0 allocation failed");
232 		return;
233 	}
234 
235 	schm(NULL, 0); /* Stop any previous measurement */
236 	schm(mb0, SCHM_MBU);
237 
238 	/* Expect success */
239 	report_prefix_push("Valid MB address and index 0");
240 	report(start_measuring(0, 0, false) &&
241 	       mb0->ssch_rsch_count == SCHM_UPDATE_CNT,
242 	       "SSCH measured %d", mb0->ssch_rsch_count);
243 	report_prefix_pop();
244 
245 	/* Clear the measurement block for the next test */
246 	memset(mb0, 0, shared_mb_size);
247 
248 	/* Expect success */
249 	report_prefix_push("Valid MB address and index 1");
250 	if (start_measuring(0, 1, false))
251 		report(mb0[1].ssch_rsch_count == SCHM_UPDATE_CNT,
252 		       "SSCH measured %d", mb0[1].ssch_rsch_count);
253 	report_prefix_pop();
254 
255 	/* Stop the measurement */
256 	css_disable_mb(test_device_sid);
257 	schm(NULL, 0);
258 
259 	free_io_mem(mb0, shared_mb_size);
260 }
261 
262 static void msch_with_wrong_fmt1_mbo(unsigned int schid, uint64_t mb)
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_fail("stsch: sch %08x failed with cc=%d", schid, cc);
271 		return;
272 	}
273 
274 	/* Update the SCHIB to enable the measurement block */
275 	pmcw->flags |= PMCW_MBUE;
276 	pmcw->flags2 |= PMCW_MBF1;
277 	schib.mbo = mb;
278 
279 	/* Tell the CSS we want to modify the subchannel */
280 	expect_pgm_int();
281 	cc = msch(schid, &schib);
282 	check_pgm_int_code(PGM_INT_CODE_OPERAND);
283 }
284 
285 /*
286  * test_schm_fmt1:
287  * With measurement block format 1 the measurement block is
288  * dedicated to a subchannel.
289  */
290 static void test_schm_fmt1(void)
291 {
292 	struct measurement_block_format1 *mb1;
293 
294 	if (!test_device_sid) {
295 		report_skip("No device");
296 		return;
297 	}
298 
299 	if (!css_test_general_feature(CSSC_EXTENDED_MEASUREMENT_BLOCK)) {
300 		report_skip("Extended measurement block not available");
301 		return;
302 	}
303 
304 	/* Allocate zeroed Measurement block */
305 	mb1 = alloc_io_mem(sizeof(struct measurement_block_format1), 0);
306 	if (!mb1) {
307 		report_abort("measurement_block_format1 allocation failed");
308 		return;
309 	}
310 
311 	schm(NULL, 0); /* Stop any previous measurement */
312 	schm(0, SCHM_MBU);
313 
314 	/* Expect error for non aligned MB */
315 	report_prefix_push("Unaligned MB origin");
316 	msch_with_wrong_fmt1_mbo(test_device_sid, (uint64_t)mb1 + 1);
317 	report_prefix_pop();
318 
319 	/* Clear the measurement block for the next test */
320 	memset(mb1, 0, sizeof(*mb1));
321 
322 	/* Expect success */
323 	report_prefix_push("Valid MB origin");
324 	if (start_measuring((u64)mb1, 0, true))
325 		report(mb1->ssch_rsch_count == SCHM_UPDATE_CNT,
326 		       "SSCH measured %d", mb1->ssch_rsch_count);
327 	report_prefix_pop();
328 
329 	/* Stop the measurement */
330 	css_disable_mb(test_device_sid);
331 	schm(NULL, 0);
332 
333 	free_io_mem(mb1, sizeof(struct measurement_block_format1));
334 }
335 
336 static void test_msch(void)
337 {
338 	int invalid_pmcw_flags[] = {0, 1, 6, 7};
339 	struct schib test_schib;
340 	uint16_t old_pmcw_flags;
341 	const int align_to = 4;
342 	int invalid_flag;
343 	int cc;
344 
345 	if (!test_device_sid) {
346 		report_skip("No device");
347 		return;
348 	}
349 
350 	cc = stsch(test_device_sid, &schib);
351 	if (cc) {
352 		report_fail("stsch: sch %08x failed with cc=%d", test_device_sid, cc);
353 		return;
354 	}
355 
356 	report_prefix_push("Unaligned");
357 	for (int i = 1; i < align_to; i *= 2) {
358 		report_prefix_pushf("%d", i);
359 
360 		expect_pgm_int();
361 		msch(test_device_sid, (struct schib *)(alignment_test_page + i));
362 		check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
363 
364 		report_prefix_pop();
365 	}
366 	report_prefix_pop();
367 
368 	report_prefix_push("Invalid SCHIB");
369 	old_pmcw_flags = schib.pmcw.flags;
370 	for (int i = 0; i < ARRAY_SIZE(invalid_pmcw_flags); i++) {
371 		invalid_flag = invalid_pmcw_flags[i];
372 
373 		report_prefix_pushf("PMCW flag bit %d set", invalid_flag);
374 
375 		schib.pmcw.flags = old_pmcw_flags | BIT(15 - invalid_flag);
376 		expect_pgm_int();
377 		msch(test_device_sid, &schib);
378 		check_pgm_int_code(PGM_INT_CODE_OPERAND);
379 
380 		cc = stsch(test_device_sid, &test_schib);
381 		report(!cc, "STSCH succeeded");
382 		report(!(test_schib.pmcw.flags & BIT(15 - invalid_flag)), "Clear on STSCH");
383 
384 		report_prefix_pop();
385 	}
386 	report_prefix_pop();
387 
388 	schib.pmcw.flags = old_pmcw_flags;
389 }
390 
391 static void check_stcrw_no_crw_available(void)
392 {
393 	uint32_t crw = 0xfeedc0fe;
394 	int cc;
395 
396 	report_prefix_push("No CRW available");
397 	cc = stcrw(&crw);
398 	report(cc == 1, "cc == 1");
399 	report(!crw, "stored zeroes in crw");
400 	report_prefix_pop();
401 }
402 
403 static int check_stcrw_crw_available(void)
404 {
405 	const uint32_t magic = 0xfeedc0fe;
406 	uint32_t crw = magic;
407 	int cc;
408 
409 	report_prefix_push("CRW available");
410 	cc = stcrw(&crw);
411 	report(!cc, "cc is zero");
412 	report(crw != magic, "stored crw");
413 	report_prefix_pop();
414 
415 	return crw;
416 }
417 
418 static uint32_t crw_get_rsc(uint32_t crw)
419 {
420 	const int rsc_begin = 4;
421 	const int rsc_end = 8;
422 
423 	return (crw & GENMASK(31 - rsc_begin, 31 - rsc_end)) >> 24;
424 }
425 
426 #define CRW_RSC_CHP 4
427 static void test_stcrw(void)
428 {
429 	const int align_to = 4;
430 	int res;
431 	uint32_t crw;
432 
433 	if (!test_device_sid) {
434 		report_skip("No device");
435 		return;
436 	}
437 
438 	report_prefix_push("Unaligned");
439 	for (int i = 1; i < align_to; i *= 2) {
440 		report_prefix_pushf("%d", i);
441 
442 		expect_pgm_int();
443 		stcrw((uint32_t *)(alignment_test_page + i));
444 		check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
445 
446 		report_prefix_pop();
447 	}
448 	report_prefix_pop();
449 
450 	report_prefix_push("No CRW available initally");
451 	check_stcrw_no_crw_available();
452 	report_prefix_pop();
453 
454 	res = css_generate_crw(test_device_sid);
455 	if (res) {
456 		report_skip("Couldn't generate CRW");
457 		report_prefix_pop();
458 		return;
459 	}
460 
461 	crw = check_stcrw_crw_available();
462 
463 	report_prefix_push("CRW available");
464 	report(crw_get_rsc(crw) == CRW_RSC_CHP, "CRW has Channel Path RSC");
465 	report_prefix_pop();
466 
467 	report_prefix_push("No more CRWs pending");
468 	check_stcrw_no_crw_available();
469 	report_prefix_pop();
470 }
471 
472 static void test_ssch(void)
473 {
474 	const int align_to = 4;
475 	struct orb orb;
476 
477 	if (!test_device_sid) {
478 		report_skip("No device");
479 		return;
480 	}
481 
482 	report_prefix_push("Unaligned");
483 	for (int i = 1; i < align_to; i *= 2) {
484 		report_prefix_pushf("%d", i);
485 
486 		expect_pgm_int();
487 		ssch(test_device_sid, (struct orb *)(alignment_test_page + i));
488 		check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
489 
490 		report_prefix_pop();
491 	}
492 	report_prefix_pop();
493 
494 	report_prefix_push("Invalid ORB");
495 
496 	memset(&orb, 0xff, sizeof(orb));
497 	expect_pgm_int();
498 	ssch(test_device_sid, &orb);
499 	check_pgm_int_code(PGM_INT_CODE_OPERAND);
500 
501 	report_prefix_pop();
502 }
503 
504 static struct {
505 	const char *name;
506 	void (*func)(void);
507 } tests[] = {
508 	/* The css_init test is needed to initialize the CSS Characteristics */
509 	{ "initialize CSS (chsc)", css_init },
510 	{ "enumerate (stsch)", test_enumerate },
511 	{ "enable (msch)", test_enable },
512 	{ "sense (ssch/tsch)", test_sense },
513 	{ "measurement block (schm)", test_schm },
514 	{ "measurement block format0", test_schm_fmt0 },
515 	{ "measurement block format1", test_schm_fmt1 },
516 	{ "msch", test_msch },
517 	{ "stcrw", test_stcrw },
518 	{ "ssch", test_ssch },
519 	{ NULL, NULL }
520 };
521 
522 int main(int argc, char *argv[])
523 {
524 	int i;
525 
526 	report_prefix_push("Channel Subsystem");
527 	enable_io_isc(0x80 >> IO_SCH_ISC);
528 	for (i = 0; tests[i].name; i++) {
529 		report_prefix_push(tests[i].name);
530 		tests[i].func();
531 		report_prefix_pop();
532 	}
533 	report_prefix_pop();
534 
535 	return report_summary();
536 }
537