xref: /kvm-unit-tests/s390x/uv-guest.c (revision fdab948bc134fb9989a8265380a55e809879418e)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Guest Ultravisor Call tests
4  *
5  * Copyright (c) 2020 IBM Corp
6  *
7  * Authors:
8  *  Janosch Frank <frankja@linux.ibm.com>
9  */
10 
11 #include <libcflat.h>
12 #include <alloc_page.h>
13 #include <asm/page.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/interrupt.h>
16 #include <asm/facility.h>
17 #include <asm/uv.h>
18 
19 static unsigned long page;
20 
21 static void test_priv(void)
22 {
23 	struct uv_cb_header uvcb = {};
24 
25 	report_prefix_push("privileged");
26 
27 	report_prefix_push("query");
28 	uvcb.cmd = UVC_CMD_QUI;
29 	uvcb.len = sizeof(struct uv_cb_qui);
30 	expect_pgm_int();
31 	enter_pstate();
32 	uv_call_once(0, (u64)&uvcb);
33 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
34 	report_prefix_pop();
35 
36 	report_prefix_push("share");
37 	uvcb.cmd = UVC_CMD_SET_SHARED_ACCESS;
38 	uvcb.len = sizeof(struct uv_cb_share);
39 	expect_pgm_int();
40 	enter_pstate();
41 	uv_call_once(0, (u64)&uvcb);
42 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
43 	report_prefix_pop();
44 
45 	report_prefix_push("unshare");
46 	uvcb.cmd = UVC_CMD_REMOVE_SHARED_ACCESS;
47 	uvcb.len = sizeof(struct uv_cb_share);
48 	expect_pgm_int();
49 	enter_pstate();
50 	uv_call_once(0, (u64)&uvcb);
51 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
52 	report_prefix_pop();
53 
54 	report_prefix_pop();
55 }
56 
57 static void test_query(void)
58 {
59 	struct uv_cb_qui uvcb = {
60 		.header.cmd = UVC_CMD_QUI,
61 		.header.len = sizeof(uvcb) - 8,
62 	};
63 	int cc;
64 
65 	report_prefix_push("query");
66 	cc = uv_call(0, (u64)&uvcb);
67 	report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length");
68 
69 	uvcb.header.len = sizeof(uvcb);
70 	cc = uv_call(0, (u64)&uvcb);
71 	report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "successful query");
72 
73 	/*
74 	 * These bits have been introduced with the very first
75 	 * Ultravisor version and are expected to always be available
76 	 * because they are basic building blocks.
77 	 */
78 	report(test_bit_inv(BIT_UVC_CMD_QUI, &uvcb.inst_calls_list[0]),
79 	       "query indicated");
80 	report(test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, &uvcb.inst_calls_list[0]),
81 	       "share indicated");
82 	report(test_bit_inv(BIT_UVC_CMD_REMOVE_SHARED_ACCESS, &uvcb.inst_calls_list[0]),
83 	       "unshare indicated");
84 	report_prefix_pop();
85 }
86 
87 static void test_sharing(void)
88 {
89 	struct uv_cb_share uvcb = {
90 		.header.cmd = UVC_CMD_SET_SHARED_ACCESS,
91 		.header.len = sizeof(uvcb) - 8,
92 		.paddr = page,
93 	};
94 	int cc;
95 
96 	report_prefix_push("share");
97 	cc = uv_call(0, (u64)&uvcb);
98 	report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length");
99 	uvcb.header.len = sizeof(uvcb);
100 	cc = uv_call(0, (u64)&uvcb);
101 	report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "share");
102 	report_prefix_pop();
103 
104 	report_prefix_push("unshare");
105 	uvcb.header.cmd = UVC_CMD_REMOVE_SHARED_ACCESS;
106 	uvcb.header.len -= 8;
107 	cc = uv_call(0, (u64)&uvcb);
108 	report(cc == 1 && uvcb.header.rc == UVC_RC_INV_LEN, "length");
109 	uvcb.header.len = sizeof(uvcb);
110 	cc = uv_call(0, (u64)&uvcb);
111 	report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "unshare");
112 	report_prefix_pop();
113 
114 	report_prefix_pop();
115 }
116 
117 static void test_invalid(void)
118 {
119 	struct uv_cb_header uvcb = {
120 		.len = 16,
121 		.cmd = 0x4242,
122 	};
123 	int cc;
124 
125 	cc = uv_call(0, (u64)&uvcb);
126 	report(cc == 1 && uvcb.rc == UVC_RC_INV_CMD, "invalid command");
127 }
128 
129 int main(void)
130 {
131 	bool has_uvc = test_facility(158);
132 
133 	report_prefix_push("uvc");
134 	if (!has_uvc) {
135 		report_skip("Ultravisor call facility is not available");
136 		goto done;
137 	}
138 
139 	page = (unsigned long)alloc_page();
140 	test_priv();
141 	test_invalid();
142 	test_query();
143 	test_sharing();
144 	free_page((void *)page);
145 done:
146 	report_prefix_pop();
147 	return report_summary();
148 }
149