xref: /kvm-unit-tests/s390x/uv-host.c (revision 484ab8dc95bc5ed500abac75ef4b16e1ea1df7b0)
128ccfb1eSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
228ccfb1eSJanosch Frank /*
318d05511SJanosch Frank  * Host Ultravisor Call tests
428ccfb1eSJanosch Frank  *
528ccfb1eSJanosch Frank  * Copyright (c) 2021 IBM Corp
628ccfb1eSJanosch Frank  *
728ccfb1eSJanosch Frank  * Authors:
828ccfb1eSJanosch Frank  *  Janosch Frank <frankja@linux.ibm.com>
928ccfb1eSJanosch Frank  */
1028ccfb1eSJanosch Frank 
1128ccfb1eSJanosch Frank #include <libcflat.h>
125bf29e09SClaudio Imbrenda #include <hardware.h>
1328ccfb1eSJanosch Frank #include <alloc.h>
1428ccfb1eSJanosch Frank #include <vmalloc.h>
1528ccfb1eSJanosch Frank #include <sclp.h>
1628ccfb1eSJanosch Frank #include <smp.h>
1728ccfb1eSJanosch Frank #include <uv.h>
1890704fe2SJanosch Frank #include <snippet.h>
1991d18441SJanosch Frank #include <mmu.h>
2028ccfb1eSJanosch Frank #include <asm/page.h>
2128ccfb1eSJanosch Frank #include <asm/pgtable.h>
2228ccfb1eSJanosch Frank #include <asm/asm-offsets.h>
2328ccfb1eSJanosch Frank #include <asm/interrupt.h>
2428ccfb1eSJanosch Frank #include <asm/facility.h>
2591d18441SJanosch Frank #include <asm/pgtable.h>
2628ccfb1eSJanosch Frank #include <asm/uv.h>
2728ccfb1eSJanosch Frank #include <asm-generic/barrier.h>
2828ccfb1eSJanosch Frank 
2928ccfb1eSJanosch Frank static struct uv_cb_qui uvcb_qui;
3028ccfb1eSJanosch Frank static struct uv_cb_init uvcb_init;
3128ccfb1eSJanosch Frank static struct uv_cb_cgc uvcb_cgc;
3228ccfb1eSJanosch Frank static struct uv_cb_csc uvcb_csc;
3328ccfb1eSJanosch Frank 
3428ccfb1eSJanosch Frank extern int diag308_load_reset(u64 code);
3528ccfb1eSJanosch Frank 
3628ccfb1eSJanosch Frank struct cmd_list {
3728ccfb1eSJanosch Frank 	const char *name;
3828ccfb1eSJanosch Frank 	uint16_t cmd;
3928ccfb1eSJanosch Frank 	uint16_t len;
4028ccfb1eSJanosch Frank 	int call_bit;
4128ccfb1eSJanosch Frank };
4228ccfb1eSJanosch Frank 
4328ccfb1eSJanosch Frank static void cpu_loop(void)
4428ccfb1eSJanosch Frank {
4528ccfb1eSJanosch Frank 	for (;;) {}
4628ccfb1eSJanosch Frank }
4728ccfb1eSJanosch Frank 
48b9ff8da5SJanosch Frank /*
49b9ff8da5SJanosch Frank  * Checks if a memory area is protected as secure memory.
50b9ff8da5SJanosch Frank  * Will return true if all pages are protected, false otherwise.
51b9ff8da5SJanosch Frank  */
52b9ff8da5SJanosch Frank static bool access_check_3d(uint8_t *access_ptr, uint64_t len)
53b9ff8da5SJanosch Frank {
54b9ff8da5SJanosch Frank 	assert(!(len & ~PAGE_MASK));
55b9ff8da5SJanosch Frank 	assert(!((uint64_t)access_ptr & ~PAGE_MASK));
56b9ff8da5SJanosch Frank 
57b9ff8da5SJanosch Frank 	while (len) {
58b9ff8da5SJanosch Frank 		expect_pgm_int();
59b9ff8da5SJanosch Frank 		READ_ONCE(*access_ptr);
60b9ff8da5SJanosch Frank 		if (clear_pgm_int() != PGM_INT_CODE_SECURE_STOR_ACCESS)
61b9ff8da5SJanosch Frank 			return false;
62b9ff8da5SJanosch Frank 		expect_pgm_int();
63b9ff8da5SJanosch Frank 		WRITE_ONCE(*access_ptr, 42);
64b9ff8da5SJanosch Frank 		if (clear_pgm_int() != PGM_INT_CODE_SECURE_STOR_ACCESS)
65b9ff8da5SJanosch Frank 			return false;
66b9ff8da5SJanosch Frank 
67b9ff8da5SJanosch Frank 		access_ptr += PAGE_SIZE;
68b9ff8da5SJanosch Frank 		len -= PAGE_SIZE;
69b9ff8da5SJanosch Frank 	}
70b9ff8da5SJanosch Frank 
71b9ff8da5SJanosch Frank 	return true;
72b9ff8da5SJanosch Frank }
73b9ff8da5SJanosch Frank 
7428ccfb1eSJanosch Frank static struct cmd_list cmds[] = {
7528ccfb1eSJanosch Frank 	{ "init", UVC_CMD_INIT_UV, sizeof(struct uv_cb_init), BIT_UVC_CMD_INIT_UV },
7628ccfb1eSJanosch Frank 	{ "create conf", UVC_CMD_CREATE_SEC_CONF, sizeof(struct uv_cb_cgc), BIT_UVC_CMD_CREATE_SEC_CONF },
7728ccfb1eSJanosch Frank 	{ "destroy conf", UVC_CMD_DESTROY_SEC_CONF, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CONF },
7828ccfb1eSJanosch Frank 	{ "create cpu", UVC_CMD_CREATE_SEC_CPU, sizeof(struct uv_cb_csc), BIT_UVC_CMD_CREATE_SEC_CPU },
7928ccfb1eSJanosch Frank 	{ "destroy cpu", UVC_CMD_DESTROY_SEC_CPU, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_DESTROY_SEC_CPU },
8028ccfb1eSJanosch Frank 	{ "conv to", UVC_CMD_CONV_TO_SEC_STOR, sizeof(struct uv_cb_cts), BIT_UVC_CMD_CONV_TO_SEC_STOR },
8128ccfb1eSJanosch Frank 	{ "conv from", UVC_CMD_CONV_FROM_SEC_STOR, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_CONV_FROM_SEC_STOR },
8228ccfb1eSJanosch Frank 	{ "set sec conf", UVC_CMD_SET_SEC_CONF_PARAMS, sizeof(struct uv_cb_ssc), BIT_UVC_CMD_SET_SEC_PARMS },
8328ccfb1eSJanosch Frank 	{ "unpack", UVC_CMD_UNPACK_IMG, sizeof(struct uv_cb_unp), BIT_UVC_CMD_UNPACK_IMG },
8428ccfb1eSJanosch Frank 	{ "verify", UVC_CMD_VERIFY_IMG, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_VERIFY_IMG },
8528ccfb1eSJanosch Frank 	{ "cpu reset", UVC_CMD_CPU_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET },
8628ccfb1eSJanosch Frank 	{ "cpu initial reset", UVC_CMD_CPU_RESET_INITIAL, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_RESET_INITIAL },
875630c446SJanosch Frank 	{ "conf clear reset", UVC_CMD_PREPARE_RESET, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_PREPARE_RESET },
8828ccfb1eSJanosch Frank 	{ "cpu clear reset", UVC_CMD_CPU_RESET_CLEAR, sizeof(struct uv_cb_nodata), BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET },
8928ccfb1eSJanosch Frank 	{ "cpu set state", UVC_CMD_CPU_SET_STATE, sizeof(struct uv_cb_cpu_set_state), BIT_UVC_CMD_CPU_SET_STATE },
9028ccfb1eSJanosch Frank 	{ "pin shared", UVC_CMD_PIN_PAGE_SHARED, sizeof(struct uv_cb_cfs), BIT_UVC_CMD_PIN_PAGE_SHARED },
9128ccfb1eSJanosch Frank 	{ "unpin shared", UVC_CMD_UNPIN_PAGE_SHARED, sizeof(struct uv_cb_cts), BIT_UVC_CMD_UNPIN_PAGE_SHARED },
9228ccfb1eSJanosch Frank 	{ NULL, 0, 0 },
9328ccfb1eSJanosch Frank };
9428ccfb1eSJanosch Frank 
955078e7a7SJanosch Frank static void test_i3(void)
965078e7a7SJanosch Frank {
975078e7a7SJanosch Frank 	struct uv_cb_header uvcb = {
985078e7a7SJanosch Frank 		.cmd = UVC_CMD_INIT_UV,
995078e7a7SJanosch Frank 		.len = sizeof(struct uv_cb_init),
1005078e7a7SJanosch Frank 	};
1015078e7a7SJanosch Frank 	unsigned long r1 = 0;
1025078e7a7SJanosch Frank 	int cc;
1035078e7a7SJanosch Frank 
1045078e7a7SJanosch Frank 	report_prefix_push("i3");
1055078e7a7SJanosch Frank 	expect_pgm_int();
1065078e7a7SJanosch Frank 	asm volatile(
1075078e7a7SJanosch Frank 		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],4,2\n"
1085078e7a7SJanosch Frank 		"		ipm	%[cc]\n"
1095078e7a7SJanosch Frank 		"		srl	%[cc],28\n"
1105078e7a7SJanosch Frank 		: [cc] "=d" (cc)
1115078e7a7SJanosch Frank 		: [r1] "a" (r1), [r2] "a" (&uvcb)
1125078e7a7SJanosch Frank 		: "memory", "cc");
1135078e7a7SJanosch Frank 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
1145078e7a7SJanosch Frank 	report_prefix_pop();
1155078e7a7SJanosch Frank }
1165078e7a7SJanosch Frank 
11728ccfb1eSJanosch Frank static void test_priv(void)
11828ccfb1eSJanosch Frank {
11928ccfb1eSJanosch Frank 	struct uv_cb_header uvcb = {};
12028ccfb1eSJanosch Frank 	uint16_t pgm;
12128ccfb1eSJanosch Frank 	int i;
12228ccfb1eSJanosch Frank 
12328ccfb1eSJanosch Frank 	report_prefix_push("privileged");
12428ccfb1eSJanosch Frank 	for (i = 0; cmds[i].name; i++) {
12528ccfb1eSJanosch Frank 		expect_pgm_int();
12628ccfb1eSJanosch Frank 		uvcb.cmd = cmds[i].cmd;
12728ccfb1eSJanosch Frank 		uvcb.len = cmds[i].len;
12828ccfb1eSJanosch Frank 		enter_pstate();
129bf0e1689SJanosch Frank 		uv_call_once(0, (uint64_t)&uvcb);
13028ccfb1eSJanosch Frank 		pgm = clear_pgm_int();
13128ccfb1eSJanosch Frank 		report(pgm == PGM_INT_CODE_PRIVILEGED_OPERATION, "%s", cmds[i].name);
13228ccfb1eSJanosch Frank 	}
13328ccfb1eSJanosch Frank 	report_prefix_pop();
13428ccfb1eSJanosch Frank }
13528ccfb1eSJanosch Frank 
136b744815eSJanosch Frank static void test_uv_uninitialized(void)
137b744815eSJanosch Frank {
138b744815eSJanosch Frank 	struct uv_cb_header uvcb = {};
139b744815eSJanosch Frank 	int i;
140b744815eSJanosch Frank 
141b744815eSJanosch Frank 	report_prefix_push("uninitialized");
142b744815eSJanosch Frank 
143b744815eSJanosch Frank 	for (i = 0; cmds[i].name; i++) {
144b744815eSJanosch Frank 		if (cmds[i].cmd == UVC_CMD_INIT_UV)
145b744815eSJanosch Frank 			continue;
146b744815eSJanosch Frank 		expect_pgm_int();
147b744815eSJanosch Frank 		uvcb.cmd = cmds[i].cmd;
148b744815eSJanosch Frank 		uvcb.len = cmds[i].len;
149b744815eSJanosch Frank 		uv_call_once(0, (uint64_t)&uvcb);
150b744815eSJanosch Frank 		report(uvcb.rc == UVC_RC_INV_STATE, "%s", cmds[i].name);
151b744815eSJanosch Frank 	}
152b744815eSJanosch Frank 	report_prefix_pop();
153b744815eSJanosch Frank }
154b744815eSJanosch Frank 
15591d18441SJanosch Frank static void test_access(void)
15691d18441SJanosch Frank {
15791d18441SJanosch Frank 	struct uv_cb_header *uvcb;
15891d18441SJanosch Frank 	void *pages =  alloc_pages(1);
15991d18441SJanosch Frank 	uint16_t pgm;
16091d18441SJanosch Frank 	int i;
16191d18441SJanosch Frank 
16291d18441SJanosch Frank 	/* Put UVCB on second page which we will protect later */
16391d18441SJanosch Frank 	uvcb = pages + PAGE_SIZE;
16491d18441SJanosch Frank 
16591d18441SJanosch Frank 	report_prefix_push("access");
16691d18441SJanosch Frank 
16791d18441SJanosch Frank 	report_prefix_push("non-crossing");
16891d18441SJanosch Frank 	protect_page(uvcb, PAGE_ENTRY_I);
16991d18441SJanosch Frank 	for (i = 0; cmds[i].name; i++) {
17091d18441SJanosch Frank 		expect_pgm_int();
17191d18441SJanosch Frank 		mb();
17291d18441SJanosch Frank 		uv_call_once(0, (uint64_t)uvcb);
17391d18441SJanosch Frank 		pgm = clear_pgm_int();
17491d18441SJanosch Frank 		report(pgm == PGM_INT_CODE_PAGE_TRANSLATION, "%s", cmds[i].name);
17591d18441SJanosch Frank 	}
17691d18441SJanosch Frank 	report_prefix_pop();
17791d18441SJanosch Frank 
17891d18441SJanosch Frank 	report_prefix_push("crossing");
17991d18441SJanosch Frank 	/*
18091d18441SJanosch Frank 	 * Put the header into the readable page 1, everything after
18191d18441SJanosch Frank 	 * the header will be on the second, invalid page.
18291d18441SJanosch Frank 	 */
18391d18441SJanosch Frank 	uvcb -= 1;
18491d18441SJanosch Frank 	for (i = 0; cmds[i].name; i++) {
18591d18441SJanosch Frank 		uvcb->cmd = cmds[i].cmd;
18691d18441SJanosch Frank 		uvcb->len = cmds[i].len;
18791d18441SJanosch Frank 
18891d18441SJanosch Frank 		expect_pgm_int();
18991d18441SJanosch Frank 		mb();
19091d18441SJanosch Frank 		uv_call_once(0, (uint64_t)uvcb);
19191d18441SJanosch Frank 		pgm = clear_pgm_int();
19291d18441SJanosch Frank 		report(pgm == PGM_INT_CODE_PAGE_TRANSLATION, "%s", cmds[i].name);
19391d18441SJanosch Frank 	}
19491d18441SJanosch Frank 	report_prefix_pop();
19591d18441SJanosch Frank 
19691d18441SJanosch Frank 	uvcb += 1;
19791d18441SJanosch Frank 	unprotect_page(uvcb, PAGE_ENTRY_I);
19891d18441SJanosch Frank 
19991d18441SJanosch Frank 	free_pages(pages);
20091d18441SJanosch Frank 	report_prefix_pop();
20191d18441SJanosch Frank }
20291d18441SJanosch Frank 
20328ccfb1eSJanosch Frank static void test_config_destroy(void)
20428ccfb1eSJanosch Frank {
20528ccfb1eSJanosch Frank 	int rc;
20628ccfb1eSJanosch Frank 	struct uv_cb_nodata uvcb = {
20728ccfb1eSJanosch Frank 		.header.cmd = UVC_CMD_DESTROY_SEC_CONF,
20828ccfb1eSJanosch Frank 		.header.len = sizeof(uvcb),
20928ccfb1eSJanosch Frank 		.handle = uvcb_cgc.guest_handle,
21028ccfb1eSJanosch Frank 	};
21128ccfb1eSJanosch Frank 
21228ccfb1eSJanosch Frank 	report_prefix_push("dsc");
21328ccfb1eSJanosch Frank 	uvcb.header.len -= 8;
21428ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
21528ccfb1eSJanosch Frank 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN,
21628ccfb1eSJanosch Frank 	       "hdr invalid length");
21728ccfb1eSJanosch Frank 	uvcb.header.len += 8;
21828ccfb1eSJanosch Frank 
21928ccfb1eSJanosch Frank 	uvcb.handle += 1;
22028ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
22128ccfb1eSJanosch Frank 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_GHANDLE, "invalid handle");
22228ccfb1eSJanosch Frank 	uvcb.handle -= 1;
22328ccfb1eSJanosch Frank 
22428ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
22528ccfb1eSJanosch Frank 	report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success");
22628ccfb1eSJanosch Frank 	report_prefix_pop();
22728ccfb1eSJanosch Frank }
22828ccfb1eSJanosch Frank 
22928ccfb1eSJanosch Frank static void test_cpu_destroy(void)
23028ccfb1eSJanosch Frank {
23128ccfb1eSJanosch Frank 	int rc;
23228ccfb1eSJanosch Frank 	struct uv_cb_nodata uvcb = {
23328ccfb1eSJanosch Frank 		.header.len = sizeof(uvcb),
23428ccfb1eSJanosch Frank 		.header.cmd = UVC_CMD_DESTROY_SEC_CPU,
23528ccfb1eSJanosch Frank 		.handle = uvcb_csc.cpu_handle,
23628ccfb1eSJanosch Frank 	};
23728ccfb1eSJanosch Frank 
23828ccfb1eSJanosch Frank 	report_prefix_push("dcpu");
23928ccfb1eSJanosch Frank 
24028ccfb1eSJanosch Frank 	uvcb.header.len -= 8;
24128ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
24228ccfb1eSJanosch Frank 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN,
24328ccfb1eSJanosch Frank 	       "hdr invalid length");
24428ccfb1eSJanosch Frank 	uvcb.header.len += 8;
24528ccfb1eSJanosch Frank 
2465bf29e09SClaudio Imbrenda 	if (!machine_is_z15()) {
24728ccfb1eSJanosch Frank 		uvcb.handle += 1;
24828ccfb1eSJanosch Frank 		rc = uv_call(0, (uint64_t)&uvcb);
24928ccfb1eSJanosch Frank 		report(rc == 1 && uvcb.header.rc == UVC_RC_INV_CHANDLE, "invalid handle");
25028ccfb1eSJanosch Frank 		uvcb.handle -= 1;
251c73cc92dSJanosch Frank 	}
25228ccfb1eSJanosch Frank 
25328ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
25428ccfb1eSJanosch Frank 	report(rc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "success");
25528ccfb1eSJanosch Frank 
25628ccfb1eSJanosch Frank 	report_prefix_pop();
25728ccfb1eSJanosch Frank }
25828ccfb1eSJanosch Frank 
259692447f2SJanosch Frank static void test_set_se_header(void)
260692447f2SJanosch Frank {
261692447f2SJanosch Frank 	struct uv_cb_ssc uvcb = {
262692447f2SJanosch Frank 		.header.cmd = UVC_CMD_SET_SEC_CONF_PARAMS,
263692447f2SJanosch Frank 		.header.len = sizeof(uvcb),
264692447f2SJanosch Frank 		.guest_handle = uvcb_cgc.guest_handle,
265692447f2SJanosch Frank 		.sec_header_origin = 0,
266692447f2SJanosch Frank 		.sec_header_len = 0x1000,
267692447f2SJanosch Frank 	};
268692447f2SJanosch Frank 	void *pages =  alloc_pages(1);
269692447f2SJanosch Frank 	void *inv;
270692447f2SJanosch Frank 	int rc;
271692447f2SJanosch Frank 
272692447f2SJanosch Frank 	report_prefix_push("sscp");
273692447f2SJanosch Frank 
274692447f2SJanosch Frank 	uvcb.header.len -= 8;
275692447f2SJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
276692447f2SJanosch Frank 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_LEN,
277692447f2SJanosch Frank 	       "hdr invalid length");
278692447f2SJanosch Frank 	uvcb.header.len += 8;
279692447f2SJanosch Frank 
280692447f2SJanosch Frank 	uvcb.guest_handle += 1;
281692447f2SJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
282692447f2SJanosch Frank 	report(rc == 1 && uvcb.header.rc == UVC_RC_INV_GHANDLE, "invalid handle");
283692447f2SJanosch Frank 	uvcb.guest_handle -= 1;
284692447f2SJanosch Frank 
285692447f2SJanosch Frank 	inv = pages + PAGE_SIZE;
286692447f2SJanosch Frank 	uvcb.sec_header_origin = (uint64_t)inv;
287692447f2SJanosch Frank 	protect_page(inv, PAGE_ENTRY_I);
288692447f2SJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
289692447f2SJanosch Frank 	report(rc == 1 && uvcb.header.rc == 0x103,
290692447f2SJanosch Frank 	       "se hdr access exception");
291692447f2SJanosch Frank 
292692447f2SJanosch Frank 	/*
293692447f2SJanosch Frank 	 * Shift the ptr so the first few DWORDs are accessible but
294692447f2SJanosch Frank 	 * the following are on an invalid page.
295692447f2SJanosch Frank 	 */
296692447f2SJanosch Frank 	uvcb.sec_header_origin -= 0x20;
297692447f2SJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
298692447f2SJanosch Frank 	report(rc == 1 && uvcb.header.rc == 0x103,
299692447f2SJanosch Frank 	       "se hdr access exception crossing");
300692447f2SJanosch Frank 	unprotect_page(inv, PAGE_ENTRY_I);
301692447f2SJanosch Frank 
302692447f2SJanosch Frank 	free_pages(pages);
303692447f2SJanosch Frank 	report_prefix_pop();
304692447f2SJanosch Frank }
305692447f2SJanosch Frank 
30628ccfb1eSJanosch Frank static void test_cpu_create(void)
30728ccfb1eSJanosch Frank {
30828ccfb1eSJanosch Frank 	int rc;
30928ccfb1eSJanosch Frank 	unsigned long tmp;
31028ccfb1eSJanosch Frank 
31128ccfb1eSJanosch Frank 	report_prefix_push("csc");
31228ccfb1eSJanosch Frank 	uvcb_csc.header.len = sizeof(uvcb_csc);
31328ccfb1eSJanosch Frank 	uvcb_csc.header.cmd = UVC_CMD_CREATE_SEC_CPU;
31428ccfb1eSJanosch Frank 	uvcb_csc.guest_handle = uvcb_cgc.guest_handle;
31528ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len);
31628ccfb1eSJanosch Frank 	uvcb_csc.state_origin = (unsigned long)memalign(PAGE_SIZE, PAGE_SIZE);
31728ccfb1eSJanosch Frank 
31828ccfb1eSJanosch Frank 	uvcb_csc.header.len -= 8;
31928ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
32028ccfb1eSJanosch Frank 	report(uvcb_csc.header.rc == UVC_RC_INV_LEN && rc == 1 &&
32128ccfb1eSJanosch Frank 	       !uvcb_csc.cpu_handle, "hdr invalid length");
32228ccfb1eSJanosch Frank 	uvcb_csc.header.len += 8;
32328ccfb1eSJanosch Frank 
32428ccfb1eSJanosch Frank 	uvcb_csc.guest_handle += 1;
32528ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
32628ccfb1eSJanosch Frank 	report(uvcb_csc.header.rc == UVC_RC_INV_GHANDLE && rc == 1,
32728ccfb1eSJanosch Frank 	       "invalid guest handle");
32828ccfb1eSJanosch Frank 	uvcb_csc.guest_handle -= 1;
32928ccfb1eSJanosch Frank 
33028ccfb1eSJanosch Frank 	uvcb_csc.num = uvcb_qui.max_guest_cpus + 1;
33128ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
33228ccfb1eSJanosch Frank 	report(uvcb_csc.header.rc == 0x103 && rc == 1,
33328ccfb1eSJanosch Frank 	       "invalid cpu #");
33428ccfb1eSJanosch Frank 	uvcb_csc.num = 0;
33528ccfb1eSJanosch Frank 
33628ccfb1eSJanosch Frank 	tmp = uvcb_csc.stor_origin;
33728ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = get_max_ram_size() + PAGE_SIZE;
33828ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
33928ccfb1eSJanosch Frank 	report(uvcb_csc.header.rc == 0x105 && rc == 1,
34028ccfb1eSJanosch Frank 	       "cpu stor inaccessible");
34128ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = tmp;
34228ccfb1eSJanosch Frank 
34328ccfb1eSJanosch Frank 	tmp = uvcb_csc.stor_origin;
34428ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = 0;
34528ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
34628ccfb1eSJanosch Frank 	report(uvcb_csc.header.rc == 0x106 && rc == 1,
34728ccfb1eSJanosch Frank 	       "cpu stor in lowcore");
34828ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = tmp;
34928ccfb1eSJanosch Frank 
35028ccfb1eSJanosch Frank 	tmp = uvcb_csc.state_origin;
35128ccfb1eSJanosch Frank 	uvcb_csc.state_origin = get_max_ram_size() + PAGE_SIZE;
35228ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
35328ccfb1eSJanosch Frank 	report(uvcb_csc.header.rc == 0x107 && rc == 1,
35428ccfb1eSJanosch Frank 	       "SIE SD inaccessible");
35528ccfb1eSJanosch Frank 	uvcb_csc.state_origin = tmp;
35628ccfb1eSJanosch Frank 
35728ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
35828ccfb1eSJanosch Frank 	report(rc == 0 && uvcb_csc.header.rc == UVC_RC_EXECUTED &&
35928ccfb1eSJanosch Frank 	       uvcb_csc.cpu_handle, "success");
36028ccfb1eSJanosch Frank 
361b9ff8da5SJanosch Frank 	rc = access_check_3d((uint8_t *)uvcb_csc.stor_origin,
362b9ff8da5SJanosch Frank 			     uvcb_qui.cpu_stor_len);
363b9ff8da5SJanosch Frank 	report(rc, "Storage protection");
364b9ff8da5SJanosch Frank 
36528ccfb1eSJanosch Frank 	tmp = uvcb_csc.stor_origin;
36628ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len);
36728ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
36828ccfb1eSJanosch Frank 	report(rc == 1 && uvcb_csc.header.rc == 0x104, "already defined");
36928ccfb1eSJanosch Frank 	uvcb_csc.stor_origin = tmp;
37028ccfb1eSJanosch Frank 	report_prefix_pop();
37128ccfb1eSJanosch Frank }
37228ccfb1eSJanosch Frank 
373*484ab8dcSJanosch Frank /*
374*484ab8dcSJanosch Frank  * If the first bit of the rc is set we need to destroy the
375*484ab8dcSJanosch Frank  * configuration before testing other create config errors.
376*484ab8dcSJanosch Frank  */
377*484ab8dcSJanosch Frank static void cgc_destroy_if_needed(struct uv_cb_cgc *uvcb)
378*484ab8dcSJanosch Frank {
379*484ab8dcSJanosch Frank 	uint16_t rc, rrc;
380*484ab8dcSJanosch Frank 
381*484ab8dcSJanosch Frank 	if (uvcb->header.rc != UVC_RC_EXECUTED &&
382*484ab8dcSJanosch Frank 	    !(uvcb->header.rc & UVC_RC_DSTR_NEEDED_FLG))
383*484ab8dcSJanosch Frank 		return;
384*484ab8dcSJanosch Frank 
385*484ab8dcSJanosch Frank 	assert(uvcb->guest_handle);
386*484ab8dcSJanosch Frank 	assert(!uv_cmd_nodata(uvcb->guest_handle, UVC_CMD_DESTROY_SEC_CONF,
387*484ab8dcSJanosch Frank 			      &rc, &rrc));
388*484ab8dcSJanosch Frank 
389*484ab8dcSJanosch Frank 	/* We need to zero it for the next test */
390*484ab8dcSJanosch Frank 	uvcb->guest_handle = 0;
391*484ab8dcSJanosch Frank }
392*484ab8dcSJanosch Frank 
393*484ab8dcSJanosch Frank static bool cgc_check_data(struct uv_cb_cgc *uvcb, uint16_t rc_expected)
394*484ab8dcSJanosch Frank {
395*484ab8dcSJanosch Frank 	/* This function purely checks for error rcs */
396*484ab8dcSJanosch Frank 	if (uvcb->header.rc == UVC_RC_EXECUTED)
397*484ab8dcSJanosch Frank 		return false;
398*484ab8dcSJanosch Frank 
399*484ab8dcSJanosch Frank 	/*
400*484ab8dcSJanosch Frank 	 * We should only receive a handle when the rc is 1 or the
401*484ab8dcSJanosch Frank 	 * first bit is set.
402*484ab8dcSJanosch Frank 	 */
403*484ab8dcSJanosch Frank 	if (!(uvcb->header.rc & UVC_RC_DSTR_NEEDED_FLG) && uvcb->guest_handle)
404*484ab8dcSJanosch Frank 		report_abort("Received a handle when we didn't expect one");
405*484ab8dcSJanosch Frank 
406*484ab8dcSJanosch Frank 	return (uvcb->header.rc & ~UVC_RC_DSTR_NEEDED_FLG) == rc_expected;
407*484ab8dcSJanosch Frank }
408*484ab8dcSJanosch Frank 
40928ccfb1eSJanosch Frank static void test_config_create(void)
41028ccfb1eSJanosch Frank {
41128ccfb1eSJanosch Frank 	int rc;
41228ccfb1eSJanosch Frank 	unsigned long vsize, tmp;
41328ccfb1eSJanosch Frank 	static struct uv_cb_cgc uvcb;
41428ccfb1eSJanosch Frank 
41528ccfb1eSJanosch Frank 	uvcb_cgc.header.cmd = UVC_CMD_CREATE_SEC_CONF;
41628ccfb1eSJanosch Frank 	uvcb_cgc.header.len = sizeof(uvcb_cgc);
41728ccfb1eSJanosch Frank 	report_prefix_push("cgc");
41828ccfb1eSJanosch Frank 
41928ccfb1eSJanosch Frank 	uvcb_cgc.guest_stor_origin = 0;
42028ccfb1eSJanosch Frank 	uvcb_cgc.guest_stor_len = 42 * (1UL << 20);
42128ccfb1eSJanosch Frank 	vsize = uvcb_qui.conf_base_virt_stor_len +
42228ccfb1eSJanosch Frank 		((uvcb_cgc.guest_stor_len / (1UL << 20)) * uvcb_qui.conf_virt_var_stor_len);
42328ccfb1eSJanosch Frank 
42428ccfb1eSJanosch Frank 	uvcb_cgc.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len);
42528ccfb1eSJanosch Frank 	uvcb_cgc.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize);
42628ccfb1eSJanosch Frank 	uvcb_cgc.guest_asce = (uint64_t)memalign(PAGE_SIZE, 4 * PAGE_SIZE) | ASCE_DT_SEGMENT | REGION_TABLE_LENGTH | ASCE_P;
42728ccfb1eSJanosch Frank 	uvcb_cgc.guest_sca = (uint64_t)memalign(PAGE_SIZE * 4, PAGE_SIZE * 4);
42828ccfb1eSJanosch Frank 
42928ccfb1eSJanosch Frank 	uvcb_cgc.header.len -= 8;
43028ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
43128ccfb1eSJanosch Frank 	report(uvcb_cgc.header.rc == UVC_RC_INV_LEN && rc == 1 &&
43228ccfb1eSJanosch Frank 	       !uvcb_cgc.guest_handle, "hdr invalid length");
433*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
43428ccfb1eSJanosch Frank 	uvcb_cgc.header.len += 8;
43528ccfb1eSJanosch Frank 
43628ccfb1eSJanosch Frank 	uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr + (1UL << 20) * 2 + 1;
43728ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
438*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x101) && rc == 1,
43928ccfb1eSJanosch Frank 	       "MSO > max guest addr");
440*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
44128ccfb1eSJanosch Frank 	uvcb_cgc.guest_stor_origin = 0;
44228ccfb1eSJanosch Frank 
44328ccfb1eSJanosch Frank 	uvcb_cgc.guest_stor_origin = uvcb_qui.max_guest_stor_addr - (1UL << 20);
44428ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
445*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x102) && rc == 1,
44628ccfb1eSJanosch Frank 	       "MSO + MSL > max guest addr");
447*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
44828ccfb1eSJanosch Frank 	uvcb_cgc.guest_stor_origin = 0;
44928ccfb1eSJanosch Frank 
45028ccfb1eSJanosch Frank 	uvcb_cgc.guest_asce &= ~ASCE_P;
45128ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
452*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x105) && rc == 1,
45328ccfb1eSJanosch Frank 	       "ASCE private bit missing");
454*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
45528ccfb1eSJanosch Frank 	uvcb_cgc.guest_asce |= ASCE_P;
45628ccfb1eSJanosch Frank 
45728ccfb1eSJanosch Frank 	uvcb_cgc.guest_asce |= 0x20;
45828ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
459*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x105) && rc == 1,
46028ccfb1eSJanosch Frank 	       "ASCE bit 58 set");
461*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
46228ccfb1eSJanosch Frank 	uvcb_cgc.guest_asce &= ~0x20;
46328ccfb1eSJanosch Frank 
46428ccfb1eSJanosch Frank 	tmp = uvcb_cgc.conf_base_stor_origin;
46528ccfb1eSJanosch Frank 	uvcb_cgc.conf_base_stor_origin = get_max_ram_size() + 8;
46628ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
467*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x108) && rc == 1,
46828ccfb1eSJanosch Frank 	       "base storage origin > available memory");
469*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
47028ccfb1eSJanosch Frank 	uvcb_cgc.conf_base_stor_origin = tmp;
47128ccfb1eSJanosch Frank 
47228ccfb1eSJanosch Frank 	tmp = uvcb_cgc.conf_base_stor_origin;
47328ccfb1eSJanosch Frank 	uvcb_cgc.conf_base_stor_origin = 0x1000;
47428ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
475*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x109) && rc == 1,
476*484ab8dcSJanosch Frank 	       "base storage origin contains lowcore %x",  uvcb_cgc.header.rc);
477*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
47828ccfb1eSJanosch Frank 	uvcb_cgc.conf_base_stor_origin = tmp;
47928ccfb1eSJanosch Frank 
48028ccfb1eSJanosch Frank 	tmp = uvcb_cgc.guest_sca;
48128ccfb1eSJanosch Frank 	uvcb_cgc.guest_sca = 0;
48228ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
483*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x10c) && rc == 1,
48428ccfb1eSJanosch Frank 	       "sca == 0");
485*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
48628ccfb1eSJanosch Frank 	uvcb_cgc.guest_sca = tmp;
48728ccfb1eSJanosch Frank 
48828ccfb1eSJanosch Frank 	tmp = uvcb_cgc.guest_sca;
4895e83f9d0SJanosch Frank 	uvcb_cgc.guest_sca = get_max_ram_size() + PAGE_SIZE * 4;
49028ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
491*484ab8dcSJanosch Frank 	report(cgc_check_data(&uvcb_cgc, 0x10d) && rc == 1,
49228ccfb1eSJanosch Frank 	       "sca inaccessible");
493*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
49428ccfb1eSJanosch Frank 	uvcb_cgc.guest_sca = tmp;
49528ccfb1eSJanosch Frank 
49628ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
49728ccfb1eSJanosch Frank 	report(rc == 0 && uvcb_cgc.header.rc == UVC_RC_EXECUTED, "successful");
49828ccfb1eSJanosch Frank 
499b9ff8da5SJanosch Frank 	rc = access_check_3d((uint8_t *)uvcb_cgc.conf_base_stor_origin,
500b9ff8da5SJanosch Frank 			     uvcb_qui.conf_base_phys_stor_len);
501b9ff8da5SJanosch Frank 	report(rc, "Base storage protection");
502b9ff8da5SJanosch Frank 
503b9ff8da5SJanosch Frank 	rc = access_check_3d((uint8_t *)uvcb_cgc.conf_var_stor_origin, vsize);
504b9ff8da5SJanosch Frank 	report(rc, "Variable storage protection");
505b9ff8da5SJanosch Frank 
50628ccfb1eSJanosch Frank 	uvcb_cgc.header.rc = 0;
50728ccfb1eSJanosch Frank 	uvcb_cgc.header.rrc = 0;
50828ccfb1eSJanosch Frank 	tmp = uvcb_cgc.guest_handle;
50928ccfb1eSJanosch Frank 	uvcb_cgc.guest_handle = 0;
51028ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
51128ccfb1eSJanosch Frank 	report(uvcb_cgc.header.rc >= 0x100 && rc == 1, "reuse uvcb");
512*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb_cgc);
51328ccfb1eSJanosch Frank 	uvcb_cgc.guest_handle = tmp;
51428ccfb1eSJanosch Frank 
51528ccfb1eSJanosch Frank 	/* Copy over most data from uvcb_cgc, so we have the ASCE that was used. */
51628ccfb1eSJanosch Frank 	memcpy(&uvcb, &uvcb_cgc, sizeof(uvcb));
51728ccfb1eSJanosch Frank 
51828ccfb1eSJanosch Frank 	/* Reset the header and handle */
51928ccfb1eSJanosch Frank 	uvcb.header.rc = 0;
52028ccfb1eSJanosch Frank 	uvcb.header.rrc = 0;
52128ccfb1eSJanosch Frank 	uvcb.guest_handle = 0;
52228ccfb1eSJanosch Frank 
52328ccfb1eSJanosch Frank 	/* Use new storage areas. */
52428ccfb1eSJanosch Frank 	uvcb.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len);
52528ccfb1eSJanosch Frank 	uvcb.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize);
52628ccfb1eSJanosch Frank 
52728ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb);
52828ccfb1eSJanosch Frank 	report(uvcb.header.rc >= 0x104 && rc == 1 && !uvcb.guest_handle,
52928ccfb1eSJanosch Frank 	       "reuse ASCE");
530*484ab8dcSJanosch Frank 	cgc_destroy_if_needed(&uvcb);
53128ccfb1eSJanosch Frank 	free((void *)uvcb.conf_base_stor_origin);
53228ccfb1eSJanosch Frank 	free((void *)uvcb.conf_var_stor_origin);
53328ccfb1eSJanosch Frank 
53428ccfb1eSJanosch Frank 	/* Missing: 106, 10a, a0b */
53528ccfb1eSJanosch Frank 	report_prefix_pop();
53628ccfb1eSJanosch Frank }
53728ccfb1eSJanosch Frank 
53828ccfb1eSJanosch Frank static void test_init(void)
53928ccfb1eSJanosch Frank {
54028ccfb1eSJanosch Frank 	int rc;
5414033c512SJanosch Frank 	uint64_t tmp;
54228ccfb1eSJanosch Frank 
5434033c512SJanosch Frank 	/*
5444033c512SJanosch Frank 	 * Donated storage needs to be over 2GB, AREA_NORMAL does that
5454033c512SJanosch Frank 	 * on s390x.
5464033c512SJanosch Frank 	 */
5474033c512SJanosch Frank 	tmp = (uint64_t)memalign_pages_flags(SZ_1M, uvcb_qui.uv_base_stor_len, AREA_NORMAL);
54828ccfb1eSJanosch Frank 
54928ccfb1eSJanosch Frank 	uvcb_init.header.len = sizeof(uvcb_init);
55028ccfb1eSJanosch Frank 	uvcb_init.header.cmd = UVC_CMD_INIT_UV;
5514033c512SJanosch Frank 	uvcb_init.stor_origin = tmp;
55228ccfb1eSJanosch Frank 	uvcb_init.stor_len = uvcb_qui.uv_base_stor_len;
55328ccfb1eSJanosch Frank 
55428ccfb1eSJanosch Frank 	report_prefix_push("init");
55528ccfb1eSJanosch Frank 	uvcb_init.header.len -= 8;
55628ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_init);
55728ccfb1eSJanosch Frank 	report(rc == 1 && uvcb_init.header.rc == UVC_RC_INV_LEN,
55828ccfb1eSJanosch Frank 	       "hdr invalid length");
55928ccfb1eSJanosch Frank 	uvcb_init.header.len += 8;
56028ccfb1eSJanosch Frank 
56128ccfb1eSJanosch Frank 	uvcb_init.stor_len -= 8;
56228ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_init);
56328ccfb1eSJanosch Frank 	report(rc == 1 && uvcb_init.header.rc == 0x103,
56428ccfb1eSJanosch Frank 	       "storage invalid length");
56528ccfb1eSJanosch Frank 	uvcb_init.stor_len += 8;
56628ccfb1eSJanosch Frank 
567fa61eb8eSJanosch Frank 	/* Storage origin is 1MB aligned, the length is 4KB aligned */
568fa61eb8eSJanosch Frank 	uvcb_init.stor_origin = get_max_ram_size();
56928ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_init);
570fa61eb8eSJanosch Frank 	report(rc == 1 && (uvcb_init.header.rc == 0x104 || uvcb_init.header.rc == 0x105),
57128ccfb1eSJanosch Frank 	       "storage origin invalid");
5724033c512SJanosch Frank 	uvcb_init.stor_origin = tmp;
57328ccfb1eSJanosch Frank 
574fa61eb8eSJanosch Frank 	if (uvcb_init.stor_len >= HPAGE_SIZE) {
575fa61eb8eSJanosch Frank 		uvcb_init.stor_origin = get_max_ram_size() - HPAGE_SIZE;
57628ccfb1eSJanosch Frank 		rc = uv_call(0, (uint64_t)&uvcb_init);
57728ccfb1eSJanosch Frank 		report(rc == 1 && uvcb_init.header.rc == 0x105,
57828ccfb1eSJanosch Frank 		       "storage + length invalid");
5794033c512SJanosch Frank 		uvcb_init.stor_origin = tmp;
580fa61eb8eSJanosch Frank 	} else {
581fa61eb8eSJanosch Frank 		report_skip("storage + length invalid, stor_len < HPAGE_SIZE");
582fa61eb8eSJanosch Frank 	}
58328ccfb1eSJanosch Frank 
58428ccfb1eSJanosch Frank 	uvcb_init.stor_origin = 1UL << 30;
58528ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_init);
58628ccfb1eSJanosch Frank 	report(rc == 1 && uvcb_init.header.rc == 0x108,
58728ccfb1eSJanosch Frank 	       "storage below 2GB");
5884033c512SJanosch Frank 	uvcb_init.stor_origin = tmp;
58928ccfb1eSJanosch Frank 
590333011bbSJanosch Frank 	if (smp_query_num_cpus() > 1) {
591f514b4f7SClaudio Imbrenda 		smp_cpu_setup(1, PSW_WITH_CUR_MASK(cpu_loop));
59228ccfb1eSJanosch Frank 		rc = uv_call(0, (uint64_t)&uvcb_init);
59328ccfb1eSJanosch Frank 		report(rc == 1 && uvcb_init.header.rc == 0x102,
59428ccfb1eSJanosch Frank 		       "too many running cpus");
59528ccfb1eSJanosch Frank 		smp_cpu_stop(1);
596333011bbSJanosch Frank 	} else {
597333011bbSJanosch Frank 		report_skip("Not enough cpus for 0x102 test");
598333011bbSJanosch Frank 	}
59928ccfb1eSJanosch Frank 
60028ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_init);
60128ccfb1eSJanosch Frank 	report(rc == 0 && uvcb_init.header.rc == UVC_RC_EXECUTED, "successful");
60228ccfb1eSJanosch Frank 
6034033c512SJanosch Frank 	tmp = uvcb_init.stor_origin;
6044033c512SJanosch Frank 	uvcb_init.stor_origin =	(uint64_t)memalign_pages_flags(HPAGE_SIZE, uvcb_qui.uv_base_stor_len, AREA_NORMAL);
60528ccfb1eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_init);
60628ccfb1eSJanosch Frank 	report(rc == 1 && uvcb_init.header.rc == 0x101, "double init");
6074033c512SJanosch Frank 	free((void *)uvcb_init.stor_origin);
6084033c512SJanosch Frank 	uvcb_init.stor_origin = tmp;
60928ccfb1eSJanosch Frank 
61028ccfb1eSJanosch Frank 	report_prefix_pop();
61128ccfb1eSJanosch Frank }
61228ccfb1eSJanosch Frank 
61328ccfb1eSJanosch Frank static void test_query(void)
61428ccfb1eSJanosch Frank {
615cde26b62SJanosch Frank 	int i = 0, cc;
61628ccfb1eSJanosch Frank 
61728ccfb1eSJanosch Frank 	uvcb_qui.header.cmd = UVC_CMD_QUI;
61828ccfb1eSJanosch Frank 	uvcb_qui.header.len = sizeof(uvcb_qui);
61928ccfb1eSJanosch Frank 
62028ccfb1eSJanosch Frank 	report_prefix_push("query");
62128ccfb1eSJanosch Frank 	uvcb_qui.header.len = 0xa0;
62228ccfb1eSJanosch Frank 	uv_call(0, (uint64_t)&uvcb_qui);
62328ccfb1eSJanosch Frank 	report(uvcb_qui.header.rc == UVC_RC_INV_LEN, "length");
62428ccfb1eSJanosch Frank 
62528ccfb1eSJanosch Frank 	uvcb_qui.header.len = 0xa8;
62628ccfb1eSJanosch Frank 	uv_call(0, (uint64_t)&uvcb_qui);
62728ccfb1eSJanosch Frank 	report(uvcb_qui.header.rc == 0x100, "insf length");
62828ccfb1eSJanosch Frank 
62928ccfb1eSJanosch Frank 	uvcb_qui.header.len = sizeof(uvcb_qui);
630cde26b62SJanosch Frank 	cc = uv_call(0, (uint64_t)&uvcb_qui);
631cde26b62SJanosch Frank 	report((!cc && uvcb_qui.header.rc == UVC_RC_EXECUTED) ||
632cde26b62SJanosch Frank 	       (cc == 1 && uvcb_qui.header.rc == 0x100),
633cde26b62SJanosch Frank 		"successful query");
63428ccfb1eSJanosch Frank 
63528ccfb1eSJanosch Frank 	for (i = 0; cmds[i].name; i++)
63628ccfb1eSJanosch Frank 		report(uv_query_test_call(cmds[i].call_bit), "%s", cmds[i].name);
63728ccfb1eSJanosch Frank 
63828ccfb1eSJanosch Frank 	report_prefix_pop();
63928ccfb1eSJanosch Frank }
64028ccfb1eSJanosch Frank 
64128ccfb1eSJanosch Frank static struct cmd_list invalid_cmds[] = {
64228ccfb1eSJanosch Frank 	{ "bogus", 0x4242, sizeof(struct uv_cb_header), -1},
64328ccfb1eSJanosch Frank 	{ "share", UVC_CMD_SET_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_SET_SHARED_ACCESS },
64428ccfb1eSJanosch Frank 	{ "unshare", UVC_CMD_REMOVE_SHARED_ACCESS, sizeof(struct uv_cb_share), BIT_UVC_CMD_REMOVE_SHARED_ACCESS },
6456a87e02cSSteffen Eiden 	{ "attest", UVC_CMD_ATTESTATION, sizeof(struct uv_cb_attest), BIT_UVC_CMD_ATTESTATION },
64628ccfb1eSJanosch Frank 	{ NULL, 0, 0 },
64728ccfb1eSJanosch Frank };
64828ccfb1eSJanosch Frank 
64928ccfb1eSJanosch Frank static void test_invalid(void)
65028ccfb1eSJanosch Frank {
65128ccfb1eSJanosch Frank 	struct uv_cb_header hdr = {};
65228ccfb1eSJanosch Frank 	int i, cc;
65328ccfb1eSJanosch Frank 
65428ccfb1eSJanosch Frank 	report_prefix_push("invalid");
65528ccfb1eSJanosch Frank 	for (i = 0; invalid_cmds[i].name; i++) {
65628ccfb1eSJanosch Frank 		hdr.cmd = invalid_cmds[i].cmd;
65728ccfb1eSJanosch Frank 		hdr.len = invalid_cmds[i].len;
65828ccfb1eSJanosch Frank 		cc = uv_call(0, (uint64_t)&hdr);
65928ccfb1eSJanosch Frank 		report(cc == 1 && hdr.rc == UVC_RC_INV_CMD &&
66028ccfb1eSJanosch Frank 		       (invalid_cmds[i].call_bit == -1 || !uv_query_test_call(invalid_cmds[i].call_bit)),
66128ccfb1eSJanosch Frank 		       "%s", invalid_cmds[i].name);
66228ccfb1eSJanosch Frank 	}
66328ccfb1eSJanosch Frank 	report_prefix_pop();
66428ccfb1eSJanosch Frank }
66528ccfb1eSJanosch Frank 
666b744815eSJanosch Frank static void setup_test_clear(void)
667b744815eSJanosch Frank {
668b744815eSJanosch Frank 	unsigned long vsize;
669b744815eSJanosch Frank 	int rc;
670b744815eSJanosch Frank 
671b744815eSJanosch Frank 	uvcb_cgc.header.cmd = UVC_CMD_CREATE_SEC_CONF;
672b744815eSJanosch Frank 	uvcb_cgc.header.len = sizeof(uvcb_cgc);
673b744815eSJanosch Frank 
674b744815eSJanosch Frank 	uvcb_cgc.guest_stor_origin = 0;
675b744815eSJanosch Frank 	uvcb_cgc.guest_stor_len = 42 * (1UL << 20);
676b744815eSJanosch Frank 	vsize = uvcb_qui.conf_base_virt_stor_len +
677b744815eSJanosch Frank 		((uvcb_cgc.guest_stor_len / (1UL << 20)) * uvcb_qui.conf_virt_var_stor_len);
678b744815eSJanosch Frank 
679b744815eSJanosch Frank 	uvcb_cgc.conf_base_stor_origin = (uint64_t)memalign(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len);
680b744815eSJanosch Frank 	uvcb_cgc.conf_var_stor_origin = (uint64_t)memalign(PAGE_SIZE, vsize);
681b744815eSJanosch Frank 	uvcb_cgc.guest_asce = (uint64_t)memalign(PAGE_SIZE, 4 * PAGE_SIZE) | ASCE_DT_SEGMENT | REGION_TABLE_LENGTH | ASCE_P;
682b744815eSJanosch Frank 	uvcb_cgc.guest_sca = (uint64_t)memalign(PAGE_SIZE * 4, PAGE_SIZE * 4);
683b744815eSJanosch Frank 
684b744815eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_cgc);
685b744815eSJanosch Frank 	assert(rc == 0);
686b744815eSJanosch Frank 
687b744815eSJanosch Frank 	uvcb_csc.header.len = sizeof(uvcb_csc);
688b744815eSJanosch Frank 	uvcb_csc.header.cmd = UVC_CMD_CREATE_SEC_CPU;
689b744815eSJanosch Frank 	uvcb_csc.guest_handle = uvcb_cgc.guest_handle;
690b744815eSJanosch Frank 	uvcb_csc.stor_origin = (unsigned long)memalign(PAGE_SIZE, uvcb_qui.cpu_stor_len);
691b744815eSJanosch Frank 	uvcb_csc.state_origin = (unsigned long)memalign(PAGE_SIZE, PAGE_SIZE);
692b744815eSJanosch Frank 
693b744815eSJanosch Frank 	rc = uv_call(0, (uint64_t)&uvcb_csc);
694b744815eSJanosch Frank 	assert(rc == 0);
695b744815eSJanosch Frank }
696b744815eSJanosch Frank 
69728ccfb1eSJanosch Frank static void test_clear(void)
69828ccfb1eSJanosch Frank {
699b744815eSJanosch Frank 	uint64_t *tmp;
700b744815eSJanosch Frank 
701b744815eSJanosch Frank 	report_prefix_push("load normal reset");
702b744815eSJanosch Frank 
703b744815eSJanosch Frank 	/*
704b744815eSJanosch Frank 	 * Setup a config and a cpu so we can check if a diag308 reset
705b744815eSJanosch Frank 	 * clears the donated memory and makes the pages unsecure.
706b744815eSJanosch Frank 	 */
707b744815eSJanosch Frank 	setup_test_clear();
70828ccfb1eSJanosch Frank 
70928ccfb1eSJanosch Frank 	diag308_load_reset(1);
71028ccfb1eSJanosch Frank 	sclp_console_setup();
711b744815eSJanosch Frank 
712b744815eSJanosch Frank 	tmp = (void *)uvcb_init.stor_origin;
713b744815eSJanosch Frank 	report(!*tmp, "uv init donated memory cleared");
714b744815eSJanosch Frank 
715b744815eSJanosch Frank 	tmp = (void *)uvcb_cgc.conf_base_stor_origin;
716b744815eSJanosch Frank 	report(!*tmp, "config base donated memory cleared");
717b744815eSJanosch Frank 
718b744815eSJanosch Frank 	tmp = (void *)uvcb_cgc.conf_base_stor_origin;
719b744815eSJanosch Frank 	report(!*tmp, "config variable donated memory cleared");
720b744815eSJanosch Frank 
721b744815eSJanosch Frank 	tmp = (void *)uvcb_csc.stor_origin;
722b744815eSJanosch Frank 	report(!*tmp, "cpu donated memory cleared after reset 1");
723b744815eSJanosch Frank 
724b744815eSJanosch Frank 	/* Check if uninitialized after reset */
725b744815eSJanosch Frank 	test_uv_uninitialized();
726b744815eSJanosch Frank 
727b744815eSJanosch Frank 	report_prefix_pop();
72828ccfb1eSJanosch Frank }
72928ccfb1eSJanosch Frank 
73028ccfb1eSJanosch Frank static void setup_vmem(void)
73128ccfb1eSJanosch Frank {
732136d73e3SJanosch Frank 	uint64_t asce;
73328ccfb1eSJanosch Frank 
7340a5b31d2SSean Christopherson 	setup_mmu(get_max_ram_size(), NULL);
735136d73e3SJanosch Frank 	/*
736136d73e3SJanosch Frank 	 * setup_mmu() will enable DAT and set the primary address
737136d73e3SJanosch Frank 	 * space but we need to have a valid home space since UV calls
738136d73e3SJanosch Frank 	 * take home space virtual addresses.
739136d73e3SJanosch Frank 	 *
740136d73e3SJanosch Frank 	 * Hence we just copy the primary asce into the home space.
741136d73e3SJanosch Frank 	 */
74228ccfb1eSJanosch Frank 	asce = stctg(1);
74328ccfb1eSJanosch Frank 	lctlg(13, asce);
74428ccfb1eSJanosch Frank }
74528ccfb1eSJanosch Frank 
74628ccfb1eSJanosch Frank int main(void)
74728ccfb1eSJanosch Frank {
74828ccfb1eSJanosch Frank 	bool has_uvc = test_facility(158);
74928ccfb1eSJanosch Frank 
75028ccfb1eSJanosch Frank 	report_prefix_push("uvc");
75128ccfb1eSJanosch Frank 	if (!has_uvc) {
75228ccfb1eSJanosch Frank 		report_skip("Ultravisor call facility is not available");
75328ccfb1eSJanosch Frank 		goto done;
75428ccfb1eSJanosch Frank 	}
7554762a72eSJanosch Frank 	if (!uv_os_is_host()) {
7564762a72eSJanosch Frank 		report_skip("This test needs to be run in a UV host environment");
7574762a72eSJanosch Frank 		goto done;
7584762a72eSJanosch Frank 	}
75928ccfb1eSJanosch Frank 
7605078e7a7SJanosch Frank 	test_i3();
76128ccfb1eSJanosch Frank 	test_priv();
76228ccfb1eSJanosch Frank 	test_invalid();
763b744815eSJanosch Frank 	test_uv_uninitialized();
76428ccfb1eSJanosch Frank 	test_query();
76590704fe2SJanosch Frank 
76690704fe2SJanosch Frank 	if (get_ram_size() < SNIPPET_PV_MIN_MEM_SIZE) {
76790704fe2SJanosch Frank 		report_skip("Not enough memory. This test needs about %ld MB of memory",
76890704fe2SJanosch Frank 			    SNIPPET_PV_MIN_MEM_SIZE / SZ_1M);
76990704fe2SJanosch Frank 		goto done;
77090704fe2SJanosch Frank 	}
77190704fe2SJanosch Frank 
77228ccfb1eSJanosch Frank 	test_init();
77328ccfb1eSJanosch Frank 
77428ccfb1eSJanosch Frank 	setup_vmem();
77591d18441SJanosch Frank 	test_access();
77691d18441SJanosch Frank 
77728ccfb1eSJanosch Frank 	test_config_create();
77828ccfb1eSJanosch Frank 	test_cpu_create();
779692447f2SJanosch Frank 	test_set_se_header();
78028ccfb1eSJanosch Frank 	test_cpu_destroy();
78128ccfb1eSJanosch Frank 	test_config_destroy();
78228ccfb1eSJanosch Frank 	test_clear();
78328ccfb1eSJanosch Frank 
78428ccfb1eSJanosch Frank done:
78528ccfb1eSJanosch Frank 	return report_summary();
78628ccfb1eSJanosch Frank }
787