xref: /kvm-unit-tests/s390x/uv-host.c (revision c865f654ffe4c5955038aaf74f702ba62f3eb014)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Guest Ultravisor Call tests
4  *
5  * Copyright (c) 2021 IBM Corp
6  *
7  * Authors:
8  *  Janosch Frank <frankja@linux.ibm.com>
9  */
10 
11 #include <libcflat.h>
12 #include <alloc.h>
13 #include <vmalloc.h>
14 #include <sclp.h>
15 #include <smp.h>
16 #include <uv.h>
17 #include <asm/page.h>
18 #include <asm/sigp.h>
19 #include <asm/pgtable.h>
20 #include <asm/asm-offsets.h>
21 #include <asm/interrupt.h>
22 #include <asm/facility.h>
23 #include <asm/uv.h>
24 #include <asm-generic/barrier.h>
25 
26 static struct uv_cb_qui uvcb_qui;
27 static struct uv_cb_init uvcb_init;
28 static struct uv_cb_cgc uvcb_cgc;
29 static struct uv_cb_csc uvcb_csc;
30 
31 extern int diag308_load_reset(u64 code);
32 
33 struct cmd_list{
34 	const char *name;
35 	uint16_t cmd;
36 	uint16_t len;
37 	int call_bit;
38 };
39 
40 static void cpu_loop(void)
41 {
42 	for (;;) {}
43 }
44 
45 static struct cmd_list cmds[] = {
46 	{ "init", UVC_CMD_INIT_UV, sizeof(struct uv_cb_init), BIT_UVC_CMD_INIT_UV },
47 	{ "create conf", UVC_CMD_CREATE_SEC_CONF, sizeof(struct uv_cb_cgc), BIT_UVC_CMD_CREATE_SEC_CONF },
48 	{ "destroy conf", UVC_CMD_DESTROY_SEC_CONF, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CONF },
49 	{ "create cpu", UVC_CMD_CREATE_SEC_CPU, sizeof(struct uv_cb_csc), BIT_UVC_CMD_CREATE_SEC_CPU },
50 	{ "destroy cpu", UVC_CMD_DESTROY_SEC_CPU, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CPU },
51 	{ "conv to", UVC_CMD_CONV_TO_SEC_STOR, sizeof(struct uv_cb_cts), BIT_UVC_CMD_CONV_TO_SEC_STOR },
52 	{ "conv from", UVC_CMD_CONV_FROM_SEC_STOR, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_CONV_FROM_SEC_STOR },
53 	{ "set sec conf", UVC_CMD_SET_SEC_CONF_PARAMS, sizeof(struct uv_cb_ssc), BIT_UVC_CMD_SET_SEC_PARMS },
54 	{ "unpack", UVC_CMD_UNPACK_IMG, sizeof(struct uv_cb_unp), BIT_UVC_CMD_UNPACK_IMG },
55 	{ "verify", UVC_CMD_VERIFY_IMG, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_VERIFY_IMG },
56 	{ "cpu reset", UVC_CMD_CPU_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET },
57 	{ "cpu initial reset", UVC_CMD_CPU_RESET_INITIAL, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET_INITIAL },
58 	{ "conf clear reset", UVC_CMD_PERF_CONF_CLEAR_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_PREPARE_CLEAR_RESET },
59 	{ "cpu clear reset", UVC_CMD_CPU_RESET_CLEAR, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET },
60 	{ "cpu set state", UVC_CMD_CPU_SET_STATE, sizeof(struct uv_cb_cpu_set_state), BIT_UVC_CMD_CPU_SET_STATE },
61 	{ "pin shared", UVC_CMD_PIN_PAGE_SHARED, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_PIN_PAGE_SHARED },
62 	{ "unpin shared", UVC_CMD_UNPIN_PAGE_SHARED, sizeof(struct uv_cb_cts), BIT_UVC_CMD_UNPIN_PAGE_SHARED },
63 	{ NULL, 0, 0 },
64 };
65 
66 static void test_priv(void)
67 {
68 	struct uv_cb_header uvcb = {};
69 	uint16_t pgm;
70 	int i;
71 
72 	report_prefix_push("privileged");
73 	for (i = 0; cmds[i].name; i++) {
74 		expect_pgm_int();
75 		uvcb.cmd = cmds[i].cmd;
76 		uvcb.len = cmds[i].len;
77 		enter_pstate();
78 		uv_call(0, (uint64_t)&uvcb);
79 		pgm = clear_pgm_int();
80 		report(pgm == PGM_INT_CODE_PRIVILEGED_OPERATION, "%s", cmds[i].name);
81 	}
82 	report_prefix_pop();
83 }
84 
85 static void test_config_destroy(void)
86 {
87 	int rc;
88 	struct uv_cb_nodata uvcb = {
89 		.header.cmd = UVC_CMD_DESTROY_SEC_CONF,
90 		.header.len = sizeof(uvcb),
91 		.handle = uvcb_cgc.guest_handle,
92 	};
93 
94 	report_prefix_push("dsc");
95 	uvcb.header.len -= 8;
96 	rc = uv_call(0, (uint64_t)&uvcb);
97 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN,
98 	       "hdr invalid length");
99 	uvcb.header.len += 8;
100 
101 	uvcb.handle += 1;
102 	rc = uv_call(0, (uint64_t)&uvcb);
103 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_GHANDLE, "invalid handle");
104 	uvcb.handle -= 1;
105 
106 	rc = uv_call(0, (uint64_t)&uvcb);
107 	report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success");
108 	report_prefix_pop();
109 }
110 
111 static void test_cpu_destroy(void)
112 {
113 	int rc;
114 	struct uv_cb_nodata uvcb = {
115 		.header.len = sizeof(uvcb),
116 		.header.cmd = UVC_CMD_DESTROY_SEC_CPU,
117 		.handle = uvcb_csc.cpu_handle,
118 	};
119 
120 	report_prefix_push("dcpu");
121 
122 	uvcb.header.len -= 8;
123 	rc = uv_call(0, (uint64_t)&uvcb);
124 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN,
125 	       "hdr invalid length");
126 	uvcb.header.len += 8;
127 
128 	uvcb.handle += 1;
129 	rc = uv_call(0, (uint64_t)&uvcb);
130 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_CHANDLE, "invalid handle");
131 	uvcb.handle -= 1;
132 
133 	rc = uv_call(0, (uint64_t)&uvcb);
134 	report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success");
135 
136 	report_prefix_pop();
137 }
138 
139 static void test_cpu_create(void)
140 {
141 	int rc;
142 	unsigned long tmp;
143 
144 	report_prefix_push("csc");
145 	uvcb_csc.header.len = sizeof(uvcb_csc);
146 	uvcb_csc.header.cmd = UVC_CMD_CREATE_SEC_CPU;
147 	uvcb_csc.guest_handle = uvcb_cgc.guest_handle;
148 	uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len);
149 	uvcb_csc.state_origin = (unsigned long)memalign(PAGE_SIZE, PAGE_SIZE);
150 
151 	uvcb_csc.header.len -= 8;
152 	rc = uv_call(0, (uint64_t)&uvcb_csc);
153 	report(uvcb_csc.header.rc == UVC_RC_INV_LEN && rc == 1 &&
154 	       !uvcb_csc.cpu_handle, "hdr invalid length");
155 	uvcb_csc.header.len += 8;
156 
157 	uvcb_csc.guest_handle += 1;
158 	rc = uv_call(0, (uint64_t)&uvcb_csc);
159 	report(uvcb_csc.header.rc == UVC_RC_INV_GHANDLE && rc == 1,
160 	       "invalid guest handle");
161 	uvcb_csc.guest_handle -= 1;
162 
163 	uvcb_csc.num = uvcb_qui.max_guest_cpus + 1;
164 	rc = uv_call(0, (uint64_t)&uvcb_csc);
165 	report(uvcb_csc.header.rc == 0x103 && rc == 1,
166 	       "invalid cpu #");
167 	uvcb_csc.num = 0;
168 
169 	tmp = uvcb_csc.stor_origin;
170 	uvcb_csc.stor_origin = get_max_ram_size() + PAGE_SIZE;
171 	rc = uv_call(0, (uint64_t)&uvcb_csc);
172 	report(uvcb_csc.header.rc == 0x105 && rc == 1,
173 	       "cpu stor inaccessible");
174 	uvcb_csc.stor_origin = tmp;
175 
176 	tmp = uvcb_csc.stor_origin;
177 	uvcb_csc.stor_origin = 0;
178 	rc = uv_call(0, (uint64_t)&uvcb_csc);
179 	report(uvcb_csc.header.rc == 0x106 && rc == 1,
180 	       "cpu stor in lowcore");
181 	uvcb_csc.stor_origin = tmp;
182 
183 	tmp = uvcb_csc.state_origin;
184 	uvcb_csc.state_origin = get_max_ram_size() + PAGE_SIZE;
185 	rc = uv_call(0, (uint64_t)&uvcb_csc);
186 	report(uvcb_csc.header.rc == 0x107 && rc == 1,
187 	       "SIE SD inaccessible");
188 	uvcb_csc.state_origin = tmp;
189 
190 	rc = uv_call(0, (uint64_t)&uvcb_csc);
191 	report(rc == 0 && uvcb_csc.header.rc == UVC_RC_EXECUTED &&
192 	       uvcb_csc.cpu_handle, "success");
193 
194 	tmp = uvcb_csc.stor_origin;
195 	uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len);
196 	rc = uv_call(0, (uint64_t)&uvcb_csc);
197 	report(rc == 1 && uvcb_csc.header.rc == 0x104, "already defined");
198 	uvcb_csc.stor_origin = tmp;
199 	report_prefix_pop();
200 }
201 
202 static void test_config_create(void)
203 {
204 	int rc;
205 	unsigned long vsize, tmp;
206 	static struct uv_cb_cgc uvcb;
207 
208 	uvcb_cgc.header.cmd = UVC_CMD_CREATE_SEC_CONF;
209 	uvcb_cgc.header.len = sizeof(uvcb_cgc);
210 	report_prefix_push("cgc");
211 
212 	uvcb_cgc.guest_stor_origin = 0;
213 	uvcb_cgc.guest_stor_len = 42 * (1UL << 20);
214 	vsize = uvcb_qui.conf_base_virt_stor_len +
215 		((uvcb_cgc.guest_stor_len / (1UL << 20)) * uvcb_qui.conf_virt_var_stor_len);
216 
217 	uvcb_cgc.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len);
218 	uvcb_cgc.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize);
219 	uvcb_cgc.guest_asce = (uint64_t)memalign(PAGE_SIZE, 4 * PAGE_SIZE) | ASCE_DT_SEGMENT | REGION_TABLE_LENGTH | ASCE_P;
220 	uvcb_cgc.guest_sca = (uint64_t)memalign(PAGE_SIZE * 4, PAGE_SIZE * 4);
221 
222 	uvcb_cgc.header.len -= 8;
223 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
224 	report(uvcb_cgc.header.rc == UVC_RC_INV_LEN && rc == 1 &&
225 	       !uvcb_cgc.guest_handle, "hdr invalid length");
226 	uvcb_cgc.header.len += 8;
227 
228 	uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr + (1UL << 20) * 2 + 1;
229 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
230 	report(uvcb_cgc.header.rc == 0x101 && rc == 1,
231 	       "MSO > max guest addr");
232 	uvcb_cgc.guest_stor_origin = 0;
233 
234 	uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr - (1UL << 20);
235 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
236 	report(uvcb_cgc.header.rc == 0x102 && rc == 1,
237 	       "MSO + MSL > max guest addr");
238 	uvcb_cgc.guest_stor_origin = 0;
239 
240 	uvcb_cgc.guest_asce &= ~ASCE_P;
241 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
242 	report(uvcb_cgc.header.rc == 0x105 && rc == 1,
243 	       "ASCE private bit missing");
244 	uvcb_cgc.guest_asce |= ASCE_P;
245 
246 	uvcb_cgc.guest_asce |= 0x20;
247 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
248 	report(uvcb_cgc.header.rc == 0x105 && rc == 1,
249 	       "ASCE bit 58 set");
250 	uvcb_cgc.guest_asce &= ~0x20;
251 
252 	tmp = uvcb_cgc.conf_base_stor_origin;
253 	uvcb_cgc.conf_base_stor_origin = get_max_ram_size() + 8;
254 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
255 	report(uvcb_cgc.header.rc == 0x108 && rc == 1,
256 	       "base storage origin > available memory");
257 	uvcb_cgc.conf_base_stor_origin = tmp;
258 
259 	tmp = uvcb_cgc.conf_base_stor_origin;
260 	uvcb_cgc.conf_base_stor_origin = 0x1000;
261 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
262 	report(uvcb_cgc.header.rc == 0x109 && rc == 1,
263 	       "base storage origin contains lowcore");
264 	uvcb_cgc.conf_base_stor_origin = tmp;
265 
266 	if (smp_query_num_cpus() == 1) {
267 		sigp_retry(1, SIGP_SET_PREFIX,
268 			   uvcb_cgc.conf_var_stor_origin + PAGE_SIZE, NULL);
269 		rc = uv_call(0, (uint64_t)&uvcb_cgc);
270 		report(uvcb_cgc.header.rc == 0x10e && rc == 1 &&
271 		       !uvcb_cgc.guest_handle, "variable storage area contains lowcore");
272 		sigp_retry(1, SIGP_SET_PREFIX, 0x0, NULL);
273 	}
274 
275 	tmp = uvcb_cgc.guest_sca;
276 	uvcb_cgc.guest_sca = 0;
277 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
278 	report(uvcb_cgc.header.rc == 0x10c && rc == 1,
279 	       "sca == 0");
280 	uvcb_cgc.guest_sca = tmp;
281 
282 	tmp = uvcb_cgc.guest_sca;
283 	uvcb_cgc.guest_sca = get_max_ram_size() + + PAGE_SIZE * 4;
284 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
285 	report(uvcb_cgc.header.rc == 0x10d && rc == 1,
286 	       "sca inaccessible");
287 	uvcb_cgc.guest_sca = tmp;
288 
289 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
290 	report(rc == 0 && uvcb_cgc.header.rc == UVC_RC_EXECUTED, "successful");
291 
292 	uvcb_cgc.header.rc = 0;
293 	uvcb_cgc.header.rrc = 0;
294 	tmp = uvcb_cgc.guest_handle;
295 	uvcb_cgc.guest_handle = 0;
296 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
297 	report(uvcb_cgc.header.rc >= 0x100 && rc == 1, "reuse uvcb");
298 	uvcb_cgc.guest_handle = tmp;
299 
300 	/* Copy over most data from uvcb_cgc, so we have the ASCE that was used. */
301 	memcpy(&uvcb, &uvcb_cgc, sizeof(uvcb));
302 
303 	/* Reset the header and handle */
304 	uvcb.header.rc = 0;
305 	uvcb.header.rrc = 0;
306 	uvcb.guest_handle = 0;
307 
308 	/* Use new storage areas. */
309 	uvcb.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len);
310 	uvcb.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize);
311 
312 	rc = uv_call(0, (uint64_t)&uvcb);
313 	report(uvcb.header.rc >= 0x104 && rc == 1 && !uvcb.guest_handle,
314 	       "reuse ASCE");
315 	free((void *)uvcb.conf_base_stor_origin);
316 	free((void *)uvcb.conf_var_stor_origin);
317 
318 	/* Missing: 106, 10a, a0b */
319 	report_prefix_pop();
320 }
321 
322 static void test_init(void)
323 {
324 	int rc;
325 	uint64_t mem;
326 	struct psw psw;
327 
328 	/* Donated storage needs to be over 2GB */
329 	mem = (uint64_t)memalign(1UL << 31, uvcb_qui.uv_base_stor_len);
330 
331 	uvcb_init.header.len = sizeof(uvcb_init);
332 	uvcb_init.header.cmd = UVC_CMD_INIT_UV;
333 	uvcb_init.stor_origin = mem;
334 	uvcb_init.stor_len = uvcb_qui.uv_base_stor_len;
335 
336 	report_prefix_push("init");
337 	uvcb_init.header.len -= 8;
338 	rc = uv_call(0, (uint64_t)&uvcb_init);
339 	report(rc == 1 && uvcb_init.header.rc == UVC_RC_INV_LEN,
340 	       "hdr invalid length");
341 	uvcb_init.header.len += 8;
342 
343 	uvcb_init.stor_len -= 8;
344 	rc = uv_call(0, (uint64_t)&uvcb_init);
345 	report(rc == 1 && uvcb_init.header.rc == 0x103,
346 	       "storage invalid length");
347 	uvcb_init.stor_len += 8;
348 
349 	uvcb_init.stor_origin =  get_max_ram_size() + 8;
350 	rc = uv_call(0, (uint64_t)&uvcb_init);
351 	report(rc == 1 && uvcb_init.header.rc == 0x104,
352 	       "storage origin invalid");
353 	uvcb_init.stor_origin = mem;
354 
355 	uvcb_init.stor_origin = get_max_ram_size() - 8;
356 	rc = uv_call(0, (uint64_t)&uvcb_init);
357 	report(rc == 1 && uvcb_init.header.rc == 0x105,
358 	       "storage + length invalid");
359 	uvcb_init.stor_origin = mem;
360 
361 	uvcb_init.stor_origin = 1UL << 30;
362 	rc = uv_call(0, (uint64_t)&uvcb_init);
363 	report(rc == 1 && uvcb_init.header.rc == 0x108,
364 	       "storage below 2GB");
365 	uvcb_init.stor_origin = mem;
366 
367 	psw.mask = extract_psw_mask();
368 	psw.addr = (unsigned long)cpu_loop;
369 	smp_cpu_setup(1, psw);
370 	rc = uv_call(0, (uint64_t)&uvcb_init);
371 	report(rc == 1 && uvcb_init.header.rc == 0x102,
372 	       "too many running cpus");
373 	smp_cpu_stop(1);
374 
375 	rc = uv_call(0, (uint64_t)&uvcb_init);
376 	report(rc == 0 && uvcb_init.header.rc == UVC_RC_EXECUTED, "successful");
377 
378 	mem = (uint64_t)memalign(1UL << 31, uvcb_qui.uv_base_stor_len);
379 	rc = uv_call(0, (uint64_t)&uvcb_init);
380 	report(rc == 1 && uvcb_init.header.rc == 0x101, "double init");
381 	free((void *)mem);
382 
383 	report_prefix_pop();
384 }
385 
386 static void test_query(void)
387 {
388 	int i = 0;
389 
390 	uvcb_qui.header.cmd = UVC_CMD_QUI;
391 	uvcb_qui.header.len = sizeof(uvcb_qui);
392 
393 	report_prefix_push("query");
394 	uvcb_qui.header.len = 0xa0;
395 	uv_call(0, (uint64_t)&uvcb_qui);
396 	report(uvcb_qui.header.rc == UVC_RC_INV_LEN, "length");
397 
398 	uvcb_qui.header.len = 0xa8;
399 	uv_call(0, (uint64_t)&uvcb_qui);
400 	report(uvcb_qui.header.rc == 0x100, "insf length");
401 
402 	uvcb_qui.header.len = sizeof(uvcb_qui);
403 	uv_call(0, (uint64_t)&uvcb_qui);
404 	report(uvcb_qui.header.rc == UVC_RC_EXECUTED, "successful query");
405 
406 	for (i = 0; cmds[i].name; i++)
407 		report(uv_query_test_call(cmds[i].call_bit), "%s", cmds[i].name);
408 
409 	report_prefix_pop();
410 }
411 
412 static struct cmd_list invalid_cmds[] = {
413 	{ "bogus", 0x4242, sizeof(struct uv_cb_header), -1},
414 	{ "share", UVC_CMD_SET_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_SET_SHARED_ACCESS },
415 	{ "unshare", UVC_CMD_REMOVE_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_REMOVE_SHARED_ACCESS },
416 	{ NULL, 0, 0 },
417 };
418 
419 static void test_invalid(void)
420 {
421 	struct uv_cb_header hdr = {};
422 	int i, cc;
423 
424 	report_prefix_push("invalid");
425 	for (i = 0; invalid_cmds[i].name; i++) {
426 		hdr.cmd = invalid_cmds[i].cmd;
427 		hdr.len = invalid_cmds[i].len;
428 		cc = uv_call(0, (uint64_t)&hdr);
429 		report(cc == 1 && hdr.rc == UVC_RC_INV_CMD &&
430 		       (invalid_cmds[i].call_bit == -1 || !uv_query_test_call(invalid_cmds[i].call_bit)),
431 		       "%s", invalid_cmds[i].name);
432 	}
433 	report_prefix_pop();
434 }
435 
436 static void test_clear(void)
437 {
438 	uint64_t *tmp = (void *)uvcb_init.stor_origin;
439 
440 	diag308_load_reset(1);
441 	sclp_console_setup();
442 	report(!*tmp, "memory cleared after reset 1");
443 }
444 
445 static void setup_vmem(void)
446 {
447 	uint64_t asce, mask;
448 
449 	setup_mmu(get_max_ram_size());
450 	asce = stctg(1);
451 	lctlg(13, asce);
452 	mask = extract_psw_mask() | 0x0000C00000000000UL;
453 	load_psw_mask(mask);
454 }
455 
456 int main(void)
457 {
458 	bool has_uvc = test_facility(158);
459 
460 	report_prefix_push("uvc");
461 	if (!has_uvc) {
462 		report_skip("Ultravisor call facility is not available");
463 		goto done;
464 	}
465 
466 	test_priv();
467 	test_invalid();
468 	test_query();
469 	test_init();
470 
471 	setup_vmem();
472 	test_config_create();
473 	test_cpu_create();
474 	test_cpu_destroy();
475 	test_config_destroy();
476 	test_clear();
477 
478 done:
479 	return report_summary();
480 }
481