xref: /linux/arch/powerpc/kvm/test-guest-state-buffer.c (revision 170aafe35cb98e0f3fbacb446ea86389fbce22ea)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #include <linux/init.h>
4 #include <linux/log2.h>
5 #include <kunit/test.h>
6 
7 #include <asm/guest-state-buffer.h>
8 
9 static void test_creating_buffer(struct kunit *test)
10 {
11 	struct kvmppc_gs_buff *gsb;
12 	size_t size = 0x100;
13 
14 	gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL);
15 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
16 
17 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb->hdr);
18 
19 	KUNIT_EXPECT_EQ(test, gsb->capacity, roundup_pow_of_two(size));
20 	KUNIT_EXPECT_EQ(test, gsb->len, sizeof(__be32));
21 
22 	kvmppc_gsb_free(gsb);
23 }
24 
25 static void test_adding_element(struct kunit *test)
26 {
27 	const struct kvmppc_gs_elem *head, *curr;
28 	union {
29 		__vector128 v;
30 		u64 dw[2];
31 	} u;
32 	int rem;
33 	struct kvmppc_gs_buff *gsb;
34 	size_t size = 0x1000;
35 	int i, rc;
36 	u64 data;
37 
38 	gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL);
39 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
40 
41 	/* Single elements, direct use of __kvmppc_gse_put() */
42 	data = 0xdeadbeef;
43 	rc = __kvmppc_gse_put(gsb, KVMPPC_GSID_GPR(0), 8, &data);
44 	KUNIT_EXPECT_GE(test, rc, 0);
45 
46 	head = kvmppc_gsb_data(gsb);
47 	KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(head), KVMPPC_GSID_GPR(0));
48 	KUNIT_EXPECT_EQ(test, kvmppc_gse_len(head), 8);
49 	data = 0;
50 	memcpy(&data, kvmppc_gse_data(head), 8);
51 	KUNIT_EXPECT_EQ(test, data, 0xdeadbeef);
52 
53 	/* Multiple elements, simple wrapper */
54 	rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(1), 0xcafef00d);
55 	KUNIT_EXPECT_GE(test, rc, 0);
56 
57 	u.dw[0] = 0x1;
58 	u.dw[1] = 0x2;
59 	rc = kvmppc_gse_put_vector128(gsb, KVMPPC_GSID_VSRS(0), &u.v);
60 	KUNIT_EXPECT_GE(test, rc, 0);
61 	u.dw[0] = 0x0;
62 	u.dw[1] = 0x0;
63 
64 	kvmppc_gsb_for_each_elem(i, curr, gsb, rem) {
65 		switch (i) {
66 		case 0:
67 			KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr),
68 					KVMPPC_GSID_GPR(0));
69 			KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8);
70 			KUNIT_EXPECT_EQ(test, kvmppc_gse_get_be64(curr),
71 					0xdeadbeef);
72 			break;
73 		case 1:
74 			KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr),
75 					KVMPPC_GSID_GPR(1));
76 			KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8);
77 			KUNIT_EXPECT_EQ(test, kvmppc_gse_get_u64(curr),
78 					0xcafef00d);
79 			break;
80 		case 2:
81 			KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr),
82 					KVMPPC_GSID_VSRS(0));
83 			KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 16);
84 			kvmppc_gse_get_vector128(curr, &u.v);
85 			KUNIT_EXPECT_EQ(test, u.dw[0], 0x1);
86 			KUNIT_EXPECT_EQ(test, u.dw[1], 0x2);
87 			break;
88 		}
89 	}
90 	KUNIT_EXPECT_EQ(test, i, 3);
91 
92 	kvmppc_gsb_reset(gsb);
93 	KUNIT_EXPECT_EQ(test, kvmppc_gsb_nelems(gsb), 0);
94 	KUNIT_EXPECT_EQ(test, kvmppc_gsb_len(gsb),
95 			sizeof(struct kvmppc_gs_header));
96 
97 	kvmppc_gsb_free(gsb);
98 }
99 
100 static void test_gs_parsing(struct kunit *test)
101 {
102 	struct kvmppc_gs_elem *gse;
103 	struct kvmppc_gs_parser gsp = { 0 };
104 	struct kvmppc_gs_buff *gsb;
105 	size_t size = 0x1000;
106 	u64 tmp1, tmp2;
107 
108 	gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL);
109 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
110 
111 	tmp1 = 0xdeadbeefull;
112 	kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), tmp1);
113 
114 	KUNIT_EXPECT_GE(test, kvmppc_gse_parse(&gsp, gsb), 0);
115 
116 	gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0));
117 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gse);
118 
119 	tmp2 = kvmppc_gse_get_u64(gse);
120 	KUNIT_EXPECT_EQ(test, tmp2, 0xdeadbeefull);
121 
122 	kvmppc_gsb_free(gsb);
123 }
124 
125 static void test_gs_bitmap(struct kunit *test)
126 {
127 	struct kvmppc_gs_bitmap gsbm = { 0 };
128 	struct kvmppc_gs_bitmap gsbm1 = { 0 };
129 	struct kvmppc_gs_bitmap gsbm2 = { 0 };
130 	u16 iden;
131 	int i, j;
132 
133 	i = 0;
134 	for (u16 iden = KVMPPC_GSID_HOST_STATE_SIZE;
135 	     iden <= KVMPPC_GSID_PROCESS_TABLE; iden++) {
136 		kvmppc_gsbm_set(&gsbm, iden);
137 		kvmppc_gsbm_set(&gsbm1, iden);
138 		KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
139 		kvmppc_gsbm_clear(&gsbm, iden);
140 		KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
141 		i++;
142 	}
143 
144 	for (u16 iden = KVMPPC_GSID_RUN_INPUT; iden <= KVMPPC_GSID_VPA;
145 	     iden++) {
146 		kvmppc_gsbm_set(&gsbm, iden);
147 		kvmppc_gsbm_set(&gsbm1, iden);
148 		KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
149 		kvmppc_gsbm_clear(&gsbm, iden);
150 		KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
151 		i++;
152 	}
153 
154 	for (u16 iden = KVMPPC_GSID_GPR(0); iden <= KVMPPC_GSE_DW_REGS_END; iden++) {
155 		kvmppc_gsbm_set(&gsbm, iden);
156 		kvmppc_gsbm_set(&gsbm1, iden);
157 		KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
158 		kvmppc_gsbm_clear(&gsbm, iden);
159 		KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
160 		i++;
161 	}
162 
163 	for (u16 iden = KVMPPC_GSID_CR; iden <= KVMPPC_GSID_PSPB; iden++) {
164 		kvmppc_gsbm_set(&gsbm, iden);
165 		kvmppc_gsbm_set(&gsbm1, iden);
166 		KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
167 		kvmppc_gsbm_clear(&gsbm, iden);
168 		KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
169 		i++;
170 	}
171 
172 	for (u16 iden = KVMPPC_GSID_VSRS(0); iden <= KVMPPC_GSID_VSRS(63);
173 	     iden++) {
174 		kvmppc_gsbm_set(&gsbm, iden);
175 		kvmppc_gsbm_set(&gsbm1, iden);
176 		KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
177 		kvmppc_gsbm_clear(&gsbm, iden);
178 		KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
179 		i++;
180 	}
181 
182 	for (u16 iden = KVMPPC_GSID_HDAR; iden <= KVMPPC_GSID_ASDR; iden++) {
183 		kvmppc_gsbm_set(&gsbm, iden);
184 		kvmppc_gsbm_set(&gsbm1, iden);
185 		KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden));
186 		kvmppc_gsbm_clear(&gsbm, iden);
187 		KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden));
188 		i++;
189 	}
190 
191 	j = 0;
192 	kvmppc_gsbm_for_each(&gsbm1, iden)
193 	{
194 		kvmppc_gsbm_set(&gsbm2, iden);
195 		j++;
196 	}
197 	KUNIT_EXPECT_EQ(test, i, j);
198 	KUNIT_EXPECT_MEMEQ(test, &gsbm1, &gsbm2, sizeof(gsbm1));
199 }
200 
201 struct kvmppc_gs_msg_test1_data {
202 	u64 a;
203 	u32 b;
204 	struct kvmppc_gs_part_table c;
205 	struct kvmppc_gs_proc_table d;
206 	struct kvmppc_gs_buff_info e;
207 };
208 
209 static size_t test1_get_size(struct kvmppc_gs_msg *gsm)
210 {
211 	size_t size = 0;
212 	u16 ids[] = {
213 		KVMPPC_GSID_PARTITION_TABLE,
214 		KVMPPC_GSID_PROCESS_TABLE,
215 		KVMPPC_GSID_RUN_INPUT,
216 		KVMPPC_GSID_GPR(0),
217 		KVMPPC_GSID_CR,
218 	};
219 
220 	for (int i = 0; i < ARRAY_SIZE(ids); i++)
221 		size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i]));
222 	return size;
223 }
224 
225 static int test1_fill_info(struct kvmppc_gs_buff *gsb,
226 			   struct kvmppc_gs_msg *gsm)
227 {
228 	struct kvmppc_gs_msg_test1_data *data = gsm->data;
229 
230 	if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_GPR(0)))
231 		kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), data->a);
232 
233 	if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_CR))
234 		kvmppc_gse_put_u32(gsb, KVMPPC_GSID_CR, data->b);
235 
236 	if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PARTITION_TABLE))
237 		kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE,
238 					  data->c);
239 
240 	if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PROCESS_TABLE))
241 		kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PARTITION_TABLE,
242 					  data->d);
243 
244 	if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT))
245 		kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT, data->e);
246 
247 	return 0;
248 }
249 
250 static int test1_refresh_info(struct kvmppc_gs_msg *gsm,
251 			      struct kvmppc_gs_buff *gsb)
252 {
253 	struct kvmppc_gs_parser gsp = { 0 };
254 	struct kvmppc_gs_msg_test1_data *data = gsm->data;
255 	struct kvmppc_gs_elem *gse;
256 	int rc;
257 
258 	rc = kvmppc_gse_parse(&gsp, gsb);
259 	if (rc < 0)
260 		return rc;
261 
262 	gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0));
263 	if (gse)
264 		data->a = kvmppc_gse_get_u64(gse);
265 
266 	gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_CR);
267 	if (gse)
268 		data->b = kvmppc_gse_get_u32(gse);
269 
270 	return 0;
271 }
272 
273 static struct kvmppc_gs_msg_ops gs_msg_test1_ops = {
274 	.get_size = test1_get_size,
275 	.fill_info = test1_fill_info,
276 	.refresh_info = test1_refresh_info,
277 };
278 
279 static void test_gs_msg(struct kunit *test)
280 {
281 	struct kvmppc_gs_msg_test1_data test1_data = {
282 		.a = 0xdeadbeef,
283 		.b = 0x1,
284 	};
285 	struct kvmppc_gs_msg *gsm;
286 	struct kvmppc_gs_buff *gsb;
287 
288 	gsm = kvmppc_gsm_new(&gs_msg_test1_ops, &test1_data, GSM_SEND,
289 			     GFP_KERNEL);
290 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsm);
291 
292 	gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), 0, 0, GFP_KERNEL);
293 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb);
294 
295 	kvmppc_gsm_include(gsm, KVMPPC_GSID_PARTITION_TABLE);
296 	kvmppc_gsm_include(gsm, KVMPPC_GSID_PROCESS_TABLE);
297 	kvmppc_gsm_include(gsm, KVMPPC_GSID_RUN_INPUT);
298 	kvmppc_gsm_include(gsm, KVMPPC_GSID_GPR(0));
299 	kvmppc_gsm_include(gsm, KVMPPC_GSID_CR);
300 
301 	kvmppc_gsm_fill_info(gsm, gsb);
302 
303 	memset(&test1_data, 0, sizeof(test1_data));
304 
305 	kvmppc_gsm_refresh_info(gsm, gsb);
306 	KUNIT_EXPECT_EQ(test, test1_data.a, 0xdeadbeef);
307 	KUNIT_EXPECT_EQ(test, test1_data.b, 0x1);
308 
309 	kvmppc_gsm_free(gsm);
310 }
311 
312 static struct kunit_case guest_state_buffer_testcases[] = {
313 	KUNIT_CASE(test_creating_buffer),
314 	KUNIT_CASE(test_adding_element),
315 	KUNIT_CASE(test_gs_bitmap),
316 	KUNIT_CASE(test_gs_parsing),
317 	KUNIT_CASE(test_gs_msg),
318 	{}
319 };
320 
321 static struct kunit_suite guest_state_buffer_test_suite = {
322 	.name = "guest_state_buffer_test",
323 	.test_cases = guest_state_buffer_testcases,
324 };
325 
326 kunit_test_suites(&guest_state_buffer_test_suite);
327 
328 MODULE_DESCRIPTION("KUnit tests for Guest State Buffer APIs");
329 MODULE_LICENSE("GPL");
330