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