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_GSID_CTRL; 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_LICENSE("GPL" ); |
329 | |