1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * vgic init sequence tests
4 *
5 * Copyright (C) 2020, Red Hat, Inc.
6 */
7 #define _GNU_SOURCE
8 #include <linux/kernel.h>
9 #include <sys/syscall.h>
10 #include <asm/kvm.h>
11 #include <asm/kvm_para.h>
12
13 #include "test_util.h"
14 #include "kvm_util.h"
15 #include "processor.h"
16
17 #define NR_VCPUS 4
18
19 #define REDIST_REGION_ATTR_ADDR(count, base, flags, index) (((uint64_t)(count) << 52) | \
20 ((uint64_t)((base) >> 16) << 16) | ((uint64_t)(flags) << 12) | index)
21 #define REG_OFFSET(vcpu, offset) (((uint64_t)vcpu << 32) | offset)
22
23 #define GICR_TYPER 0x8
24
25 struct vm_gic {
26 struct kvm_vm *vm;
27 int gic_fd;
28 };
29
30 static int max_ipa_bits;
31
32 /* helper to access a redistributor register */
access_redist_reg(int gicv3_fd,int vcpu,int offset,uint32_t * val,bool write)33 static int access_redist_reg(int gicv3_fd, int vcpu, int offset,
34 uint32_t *val, bool write)
35 {
36 uint64_t attr = REG_OFFSET(vcpu, offset);
37
38 return _kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
39 attr, val, write);
40 }
41
42 /* dummy guest code */
guest_code(void)43 static void guest_code(void)
44 {
45 GUEST_SYNC(0);
46 GUEST_SYNC(1);
47 GUEST_SYNC(2);
48 GUEST_DONE();
49 }
50
51 /* we don't want to assert on run execution, hence that helper */
run_vcpu(struct kvm_vm * vm,uint32_t vcpuid)52 static int run_vcpu(struct kvm_vm *vm, uint32_t vcpuid)
53 {
54 ucall_init(vm, NULL);
55 int ret = _vcpu_ioctl(vm, vcpuid, KVM_RUN, NULL);
56 if (ret)
57 return -errno;
58 return 0;
59 }
60
vm_gic_create(void)61 static struct vm_gic vm_gic_create(void)
62 {
63 struct vm_gic v;
64
65 v.vm = vm_create_default_with_vcpus(NR_VCPUS, 0, 0, guest_code, NULL);
66 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
67
68 return v;
69 }
70
vm_gic_destroy(struct vm_gic * v)71 static void vm_gic_destroy(struct vm_gic *v)
72 {
73 close(v->gic_fd);
74 kvm_vm_free(v->vm);
75 }
76
77 /**
78 * Helper routine that performs KVM device tests in general and
79 * especially ARM_VGIC_V3 ones. Eventually the ARM_VGIC_V3
80 * device gets created, a legacy RDIST region is set at @0x0
81 * and a DIST region is set @0x60000
82 */
subtest_dist_rdist(struct vm_gic * v)83 static void subtest_dist_rdist(struct vm_gic *v)
84 {
85 int ret;
86 uint64_t addr;
87
88 /* Check existing group/attributes */
89 kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
90 KVM_VGIC_V3_ADDR_TYPE_DIST);
91
92 kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
93 KVM_VGIC_V3_ADDR_TYPE_REDIST);
94
95 /* check non existing attribute */
96 ret = _kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, 0);
97 TEST_ASSERT(ret && errno == ENXIO, "attribute not supported");
98
99 /* misaligned DIST and REDIST address settings */
100 addr = 0x1000;
101 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
102 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true);
103 TEST_ASSERT(ret && errno == EINVAL, "GICv3 dist base not 64kB aligned");
104
105 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
106 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
107 TEST_ASSERT(ret && errno == EINVAL, "GICv3 redist base not 64kB aligned");
108
109 /* out of range address */
110 if (max_ipa_bits) {
111 addr = 1ULL << max_ipa_bits;
112 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
113 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true);
114 TEST_ASSERT(ret && errno == E2BIG, "dist address beyond IPA limit");
115
116 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
117 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
118 TEST_ASSERT(ret && errno == E2BIG, "redist address beyond IPA limit");
119 }
120
121 /* set REDIST base address @0x0*/
122 addr = 0x00000;
123 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
124 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
125
126 /* Attempt to create a second legacy redistributor region */
127 addr = 0xE0000;
128 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
129 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
130 TEST_ASSERT(ret && errno == EEXIST, "GICv3 redist base set again");
131
132 /* Attempt to mix legacy and new redistributor regions */
133 addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 0, 0);
134 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
135 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
136 TEST_ASSERT(ret && errno == EINVAL, "attempt to mix GICv3 REDIST and REDIST_REGION");
137
138 /*
139 * Set overlapping DIST / REDIST, cannot be detected here. Will be detected
140 * on first vcpu run instead.
141 */
142 addr = 3 * 2 * 0x10000;
143 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V3_ADDR_TYPE_DIST,
144 &addr, true);
145 }
146
147 /* Test the new REDIST region API */
subtest_redist_regions(struct vm_gic * v)148 static void subtest_redist_regions(struct vm_gic *v)
149 {
150 uint64_t addr, expected_addr;
151 int ret;
152
153 ret = kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
154 KVM_VGIC_V3_ADDR_TYPE_REDIST);
155 TEST_ASSERT(!ret, "Multiple redist regions advertised");
156
157 addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 2, 0);
158 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
159 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
160 TEST_ASSERT(ret && errno == EINVAL, "redist region attr value with flags != 0");
161
162 addr = REDIST_REGION_ATTR_ADDR(0, 0x100000, 0, 0);
163 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
164 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
165 TEST_ASSERT(ret && errno == EINVAL, "redist region attr value with count== 0");
166
167 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
168 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
169 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
170 TEST_ASSERT(ret && errno == EINVAL,
171 "attempt to register the first rdist region with index != 0");
172
173 addr = REDIST_REGION_ATTR_ADDR(2, 0x201000, 0, 1);
174 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
175 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
176 TEST_ASSERT(ret && errno == EINVAL, "rdist region with misaligned address");
177
178 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
179 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
180 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
181
182 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
183 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
184 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
185 TEST_ASSERT(ret && errno == EINVAL, "register an rdist region with already used index");
186
187 addr = REDIST_REGION_ATTR_ADDR(1, 0x210000, 0, 2);
188 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
189 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
190 TEST_ASSERT(ret && errno == EINVAL,
191 "register an rdist region overlapping with another one");
192
193 addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 2);
194 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
195 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
196 TEST_ASSERT(ret && errno == EINVAL, "register redist region with index not +1");
197
198 addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
199 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
200 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
201
202 addr = REDIST_REGION_ATTR_ADDR(1, 1ULL << max_ipa_bits, 0, 2);
203 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
204 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
205 TEST_ASSERT(ret && errno == E2BIG,
206 "register redist region with base address beyond IPA range");
207
208 addr = 0x260000;
209 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
210 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
211 TEST_ASSERT(ret && errno == EINVAL,
212 "Mix KVM_VGIC_V3_ADDR_TYPE_REDIST and REDIST_REGION");
213
214 /*
215 * Now there are 2 redist regions:
216 * region 0 @ 0x200000 2 redists
217 * region 1 @ 0x240000 1 redist
218 * Attempt to read their characteristics
219 */
220
221 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 0);
222 expected_addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
223 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
224 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false);
225 TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #0");
226
227 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 1);
228 expected_addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
229 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
230 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false);
231 TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #1");
232
233 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 2);
234 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
235 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false);
236 TEST_ASSERT(ret && errno == ENOENT, "read characteristics of non existing region");
237
238 addr = 0x260000;
239 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
240 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true);
241
242 addr = REDIST_REGION_ATTR_ADDR(1, 0x260000, 0, 2);
243 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
244 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
245 TEST_ASSERT(ret && errno == EINVAL, "register redist region colliding with dist");
246 }
247
248 /*
249 * VGIC KVM device is created and initialized before the secondary CPUs
250 * get created
251 */
test_vgic_then_vcpus(void)252 static void test_vgic_then_vcpus(void)
253 {
254 struct vm_gic v;
255 int ret, i;
256
257 v.vm = vm_create_default(0, 0, guest_code);
258 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
259
260 subtest_dist_rdist(&v);
261
262 /* Add the rest of the VCPUs */
263 for (i = 1; i < NR_VCPUS; ++i)
264 vm_vcpu_add_default(v.vm, i, guest_code);
265
266 ret = run_vcpu(v.vm, 3);
267 TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run");
268
269 vm_gic_destroy(&v);
270 }
271
272 /* All the VCPUs are created before the VGIC KVM device gets initialized */
test_vcpus_then_vgic(void)273 static void test_vcpus_then_vgic(void)
274 {
275 struct vm_gic v;
276 int ret;
277
278 v = vm_gic_create();
279
280 subtest_dist_rdist(&v);
281
282 ret = run_vcpu(v.vm, 3);
283 TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run");
284
285 vm_gic_destroy(&v);
286 }
287
test_new_redist_regions(void)288 static void test_new_redist_regions(void)
289 {
290 void *dummy = NULL;
291 struct vm_gic v;
292 uint64_t addr;
293 int ret;
294
295 v = vm_gic_create();
296 subtest_redist_regions(&v);
297 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
298 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
299
300 ret = run_vcpu(v.vm, 3);
301 TEST_ASSERT(ret == -ENXIO, "running without sufficient number of rdists");
302 vm_gic_destroy(&v);
303
304 /* step2 */
305
306 v = vm_gic_create();
307 subtest_redist_regions(&v);
308
309 addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
310 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
311 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
312
313 ret = run_vcpu(v.vm, 3);
314 TEST_ASSERT(ret == -EBUSY, "running without vgic explicit init");
315
316 vm_gic_destroy(&v);
317
318 /* step 3 */
319
320 v = vm_gic_create();
321 subtest_redist_regions(&v);
322
323 _kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
324 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, dummy, true);
325 TEST_ASSERT(ret && errno == EFAULT,
326 "register a third region allowing to cover the 4 vcpus");
327
328 addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
329 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
330 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
331
332 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
333 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
334
335 ret = run_vcpu(v.vm, 3);
336 TEST_ASSERT(!ret, "vcpu run");
337
338 vm_gic_destroy(&v);
339 }
340
test_typer_accesses(void)341 static void test_typer_accesses(void)
342 {
343 struct vm_gic v;
344 uint64_t addr;
345 uint32_t val;
346 int ret, i;
347
348 v.vm = vm_create_default(0, 0, guest_code);
349
350 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
351
352 vm_vcpu_add_default(v.vm, 3, guest_code);
353
354 ret = access_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
355 TEST_ASSERT(ret && errno == EINVAL, "attempting to read GICR_TYPER of non created vcpu");
356
357 vm_vcpu_add_default(v.vm, 1, guest_code);
358
359 ret = access_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
360 TEST_ASSERT(ret && errno == EBUSY, "read GICR_TYPER before GIC initialized");
361
362 vm_vcpu_add_default(v.vm, 2, guest_code);
363
364 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
365 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
366
367 for (i = 0; i < NR_VCPUS ; i++) {
368 ret = access_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
369 TEST_ASSERT(!ret && !val, "read GICR_TYPER before rdist region setting");
370 }
371
372 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
373 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
374 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
375
376 /* The 2 first rdists should be put there (vcpu 0 and 3) */
377 ret = access_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
378 TEST_ASSERT(!ret && !val, "read typer of rdist #0");
379
380 ret = access_redist_reg(v.gic_fd, 3, GICR_TYPER, &val, false);
381 TEST_ASSERT(!ret && val == 0x310, "read typer of rdist #1");
382
383 addr = REDIST_REGION_ATTR_ADDR(10, 0x100000, 0, 1);
384 ret = _kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
385 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
386 TEST_ASSERT(ret && errno == EINVAL, "collision with previous rdist region");
387
388 ret = access_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
389 TEST_ASSERT(!ret && val == 0x100,
390 "no redist region attached to vcpu #1 yet, last cannot be returned");
391
392 ret = access_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
393 TEST_ASSERT(!ret && val == 0x200,
394 "no redist region attached to vcpu #2, last cannot be returned");
395
396 addr = REDIST_REGION_ATTR_ADDR(10, 0x20000, 0, 1);
397 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
398 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
399
400 ret = access_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
401 TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1");
402
403 ret = access_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
404 TEST_ASSERT(!ret && val == 0x210,
405 "read typer of rdist #1, last properly returned");
406
407 vm_gic_destroy(&v);
408 }
409
410 /**
411 * Test GICR_TYPER last bit with new redist regions
412 * rdist regions #1 and #2 are contiguous
413 * rdist region #0 @0x100000 2 rdist capacity
414 * rdists: 0, 3 (Last)
415 * rdist region #1 @0x240000 2 rdist capacity
416 * rdists: 5, 4 (Last)
417 * rdist region #2 @0x200000 2 rdist capacity
418 * rdists: 1, 2
419 */
test_last_bit_redist_regions(void)420 static void test_last_bit_redist_regions(void)
421 {
422 uint32_t vcpuids[] = { 0, 3, 5, 4, 1, 2 };
423 struct vm_gic v;
424 uint64_t addr;
425 uint32_t val;
426 int ret;
427
428 v.vm = vm_create_default_with_vcpus(6, 0, 0, guest_code, vcpuids);
429
430 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
431
432 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
433 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
434
435 addr = REDIST_REGION_ATTR_ADDR(2, 0x100000, 0, 0);
436 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
437 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
438
439 addr = REDIST_REGION_ATTR_ADDR(2, 0x240000, 0, 1);
440 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
441 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
442
443 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 2);
444 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
445 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
446
447 ret = access_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
448 TEST_ASSERT(!ret && val == 0x000, "read typer of rdist #0");
449
450 ret = access_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
451 TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1");
452
453 ret = access_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
454 TEST_ASSERT(!ret && val == 0x200, "read typer of rdist #2");
455
456 ret = access_redist_reg(v.gic_fd, 3, GICR_TYPER, &val, false);
457 TEST_ASSERT(!ret && val == 0x310, "read typer of rdist #3");
458
459 ret = access_redist_reg(v.gic_fd, 5, GICR_TYPER, &val, false);
460 TEST_ASSERT(!ret && val == 0x500, "read typer of rdist #5");
461
462 ret = access_redist_reg(v.gic_fd, 4, GICR_TYPER, &val, false);
463 TEST_ASSERT(!ret && val == 0x410, "read typer of rdist #4");
464
465 vm_gic_destroy(&v);
466 }
467
468 /* Test last bit with legacy region */
test_last_bit_single_rdist(void)469 static void test_last_bit_single_rdist(void)
470 {
471 uint32_t vcpuids[] = { 0, 3, 5, 4, 1, 2 };
472 struct vm_gic v;
473 uint64_t addr;
474 uint32_t val;
475 int ret;
476
477 v.vm = vm_create_default_with_vcpus(6, 0, 0, guest_code, vcpuids);
478
479 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
480
481 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
482 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
483
484 addr = 0x10000;
485 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
486 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
487
488 ret = access_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
489 TEST_ASSERT(!ret && val == 0x000, "read typer of rdist #0");
490
491 ret = access_redist_reg(v.gic_fd, 3, GICR_TYPER, &val, false);
492 TEST_ASSERT(!ret && val == 0x300, "read typer of rdist #1");
493
494 ret = access_redist_reg(v.gic_fd, 5, GICR_TYPER, &val, false);
495 TEST_ASSERT(!ret && val == 0x500, "read typer of rdist #2");
496
497 ret = access_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
498 TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #3");
499
500 ret = access_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
501 TEST_ASSERT(!ret && val == 0x210, "read typer of rdist #3");
502
503 vm_gic_destroy(&v);
504 }
505
test_kvm_device(void)506 void test_kvm_device(void)
507 {
508 struct vm_gic v;
509 int ret, fd;
510
511 v.vm = vm_create_default_with_vcpus(NR_VCPUS, 0, 0, guest_code, NULL);
512
513 /* try to create a non existing KVM device */
514 ret = _kvm_create_device(v.vm, 0, true, &fd);
515 TEST_ASSERT(ret && errno == ENODEV, "unsupported device");
516
517 /* trial mode with VGIC_V3 device */
518 ret = _kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, true, &fd);
519 if (ret) {
520 print_skip("GICv3 not supported");
521 exit(KSFT_SKIP);
522 }
523 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
524
525 ret = _kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false, &fd);
526 TEST_ASSERT(ret && errno == EEXIST, "create GICv3 device twice");
527
528 kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, true);
529
530 if (!_kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V2, true, &fd)) {
531 ret = _kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V2, false, &fd);
532 TEST_ASSERT(ret && errno == EINVAL, "create GICv2 while v3 exists");
533 }
534
535 vm_gic_destroy(&v);
536 }
537
main(int ac,char ** av)538 int main(int ac, char **av)
539 {
540 max_ipa_bits = kvm_check_cap(KVM_CAP_ARM_VM_IPA_SIZE);
541
542 test_kvm_device();
543 test_vcpus_then_vgic();
544 test_vgic_then_vcpus();
545 test_new_redist_regions();
546 test_typer_accesses();
547 test_last_bit_redist_regions();
548 test_last_bit_single_rdist();
549
550 return 0;
551 }
552