1 // SPDX-License-Identifier: GPL-2.0
3 * vgic init sequence tests
5 * Copyright (C) 2020, Red Hat, Inc.
7 #include <linux/kernel.h>
8 #include <sys/syscall.h>
10 #include <asm/kvm_para.h>
12 #include "test_util.h"
14 #include "processor.h"
19 #define REG_OFFSET(vcpu, offset) (((uint64_t)vcpu << 32) | offset)
21 #define GICR_TYPER 0x8
23 #define VGIC_DEV_IS_V2(_d) ((_d) == KVM_DEV_TYPE_ARM_VGIC_V2)
24 #define VGIC_DEV_IS_V3(_d) ((_d) == KVM_DEV_TYPE_ARM_VGIC_V3)
29 uint32_t gic_dev_type
;
32 static uint64_t max_phys_size
;
35 * Helpers to access a redistributor register and verify the ioctl() failed or
36 * succeeded as expected, and provided the correct value on success.
38 static void v3_redist_reg_get_errno(int gicv3_fd
, int vcpu
, int offset
,
39 int want
, const char *msg
)
42 int ret
= __kvm_device_attr_get(gicv3_fd
, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
,
43 REG_OFFSET(vcpu
, offset
), &ignored_val
);
45 TEST_ASSERT(ret
&& errno
== want
, "%s; want errno = %d", msg
, want
);
48 static void v3_redist_reg_get(int gicv3_fd
, int vcpu
, int offset
, uint32_t want
,
53 kvm_device_attr_get(gicv3_fd
, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
,
54 REG_OFFSET(vcpu
, offset
), &val
);
55 TEST_ASSERT(val
== want
, "%s; want '0x%x', got '0x%x'", msg
, want
, val
);
58 /* dummy guest code */
59 static void guest_code(void)
67 /* we don't want to assert on run execution, hence that helper */
68 static int run_vcpu(struct kvm_vcpu
*vcpu
)
70 return __vcpu_run(vcpu
) ? -errno
: 0;
73 static struct vm_gic
vm_gic_create_with_vcpus(uint32_t gic_dev_type
,
75 struct kvm_vcpu
*vcpus
[])
79 v
.gic_dev_type
= gic_dev_type
;
80 v
.vm
= vm_create_with_vcpus(nr_vcpus
, guest_code
, vcpus
);
81 v
.gic_fd
= kvm_create_device(v
.vm
, gic_dev_type
);
86 static struct vm_gic
vm_gic_create_barebones(uint32_t gic_dev_type
)
90 v
.gic_dev_type
= gic_dev_type
;
91 v
.vm
= vm_create_barebones();
92 v
.gic_fd
= kvm_create_device(v
.vm
, gic_dev_type
);
98 static void vm_gic_destroy(struct vm_gic
*v
)
104 struct vgic_region_attr
{
110 struct vgic_region_attr gic_v3_dist_region
= {
111 .attr
= KVM_VGIC_V3_ADDR_TYPE_DIST
,
113 .alignment
= 0x10000,
116 struct vgic_region_attr gic_v3_redist_region
= {
117 .attr
= KVM_VGIC_V3_ADDR_TYPE_REDIST
,
118 .size
= NR_VCPUS
* 0x20000,
119 .alignment
= 0x10000,
122 struct vgic_region_attr gic_v2_dist_region
= {
123 .attr
= KVM_VGIC_V2_ADDR_TYPE_DIST
,
128 struct vgic_region_attr gic_v2_cpu_region
= {
129 .attr
= KVM_VGIC_V2_ADDR_TYPE_CPU
,
135 * Helper routine that performs KVM device tests in general. Eventually the
136 * ARM_VGIC (GICv2 or GICv3) device gets created with an overlapping
137 * DIST/REDIST (or DIST/CPUIF for GICv2). Assumption is 4 vcpus are going to be
138 * used hence the overlap. In the case of GICv3, A RDIST region is set at @0x0
139 * and a DIST region is set @0x70000. The GICv2 case sets a CPUIF @0x0 and a
140 * DIST region @0x1000.
142 static void subtest_dist_rdist(struct vm_gic
*v
)
146 struct vgic_region_attr rdist
; /* CPU interface in GICv2*/
147 struct vgic_region_attr dist
;
149 rdist
= VGIC_DEV_IS_V3(v
->gic_dev_type
) ? gic_v3_redist_region
151 dist
= VGIC_DEV_IS_V3(v
->gic_dev_type
) ? gic_v3_dist_region
152 : gic_v2_dist_region
;
154 /* Check existing group/attributes */
155 kvm_has_device_attr(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
, dist
.attr
);
157 kvm_has_device_attr(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
, rdist
.attr
);
159 /* check non existing attribute */
160 ret
= __kvm_has_device_attr(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
, -1);
161 TEST_ASSERT(ret
&& errno
== ENXIO
, "attribute not supported");
163 /* misaligned DIST and REDIST address settings */
164 addr
= dist
.alignment
/ 0x10;
165 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
167 TEST_ASSERT(ret
&& errno
== EINVAL
, "GIC dist base not aligned");
169 addr
= rdist
.alignment
/ 0x10;
170 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
172 TEST_ASSERT(ret
&& errno
== EINVAL
, "GIC redist/cpu base not aligned");
174 /* out of range address */
175 addr
= max_phys_size
;
176 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
178 TEST_ASSERT(ret
&& errno
== E2BIG
, "dist address beyond IPA limit");
180 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
182 TEST_ASSERT(ret
&& errno
== E2BIG
, "redist address beyond IPA limit");
184 /* Space for half a rdist (a rdist is: 2 * rdist.alignment). */
185 addr
= max_phys_size
- dist
.alignment
;
186 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
188 TEST_ASSERT(ret
&& errno
== E2BIG
,
189 "half of the redist is beyond IPA limit");
191 /* set REDIST base address @0x0*/
193 kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
196 /* Attempt to create a second legacy redistributor region */
198 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
200 TEST_ASSERT(ret
&& errno
== EEXIST
, "GIC redist base set again");
202 ret
= __kvm_has_device_attr(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
203 KVM_VGIC_V3_ADDR_TYPE_REDIST
);
205 /* Attempt to mix legacy and new redistributor regions */
206 addr
= REDIST_REGION_ATTR_ADDR(NR_VCPUS
, 0x100000, 0, 0);
207 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
208 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
209 TEST_ASSERT(ret
&& errno
== EINVAL
,
210 "attempt to mix GICv3 REDIST and REDIST_REGION");
214 * Set overlapping DIST / REDIST, cannot be detected here. Will be detected
215 * on first vcpu run instead.
217 addr
= rdist
.size
- rdist
.alignment
;
218 kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
222 /* Test the new REDIST region API */
223 static void subtest_v3_redist_regions(struct vm_gic
*v
)
225 uint64_t addr
, expected_addr
;
228 ret
= __kvm_has_device_attr(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
229 KVM_VGIC_V3_ADDR_TYPE_REDIST
);
230 TEST_ASSERT(!ret
, "Multiple redist regions advertised");
232 addr
= REDIST_REGION_ATTR_ADDR(NR_VCPUS
, 0x100000, 2, 0);
233 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
234 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
235 TEST_ASSERT(ret
&& errno
== EINVAL
, "redist region attr value with flags != 0");
237 addr
= REDIST_REGION_ATTR_ADDR(0, 0x100000, 0, 0);
238 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
239 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
240 TEST_ASSERT(ret
&& errno
== EINVAL
, "redist region attr value with count== 0");
242 addr
= REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
243 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
244 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
245 TEST_ASSERT(ret
&& errno
== EINVAL
,
246 "attempt to register the first rdist region with index != 0");
248 addr
= REDIST_REGION_ATTR_ADDR(2, 0x201000, 0, 1);
249 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
250 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
251 TEST_ASSERT(ret
&& errno
== EINVAL
, "rdist region with misaligned address");
253 addr
= REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
254 kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
255 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
257 addr
= REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
258 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
259 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
260 TEST_ASSERT(ret
&& errno
== EINVAL
, "register an rdist region with already used index");
262 addr
= REDIST_REGION_ATTR_ADDR(1, 0x210000, 0, 2);
263 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
264 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
265 TEST_ASSERT(ret
&& errno
== EINVAL
,
266 "register an rdist region overlapping with another one");
268 addr
= REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 2);
269 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
270 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
271 TEST_ASSERT(ret
&& errno
== EINVAL
, "register redist region with index not +1");
273 addr
= REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
274 kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
275 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
277 addr
= REDIST_REGION_ATTR_ADDR(1, max_phys_size
, 0, 2);
278 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
279 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
280 TEST_ASSERT(ret
&& errno
== E2BIG
,
281 "register redist region with base address beyond IPA range");
283 /* The last redist is above the pa range. */
284 addr
= REDIST_REGION_ATTR_ADDR(2, max_phys_size
- 0x30000, 0, 2);
285 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
286 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
287 TEST_ASSERT(ret
&& errno
== E2BIG
,
288 "register redist region with top address beyond IPA range");
291 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
292 KVM_VGIC_V3_ADDR_TYPE_REDIST
, &addr
);
293 TEST_ASSERT(ret
&& errno
== EINVAL
,
294 "Mix KVM_VGIC_V3_ADDR_TYPE_REDIST and REDIST_REGION");
297 * Now there are 2 redist regions:
298 * region 0 @ 0x200000 2 redists
299 * region 1 @ 0x240000 1 redist
300 * Attempt to read their characteristics
303 addr
= REDIST_REGION_ATTR_ADDR(0, 0, 0, 0);
304 expected_addr
= REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
305 ret
= __kvm_device_attr_get(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
306 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
307 TEST_ASSERT(!ret
&& addr
== expected_addr
, "read characteristics of region #0");
309 addr
= REDIST_REGION_ATTR_ADDR(0, 0, 0, 1);
310 expected_addr
= REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
311 ret
= __kvm_device_attr_get(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
312 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
313 TEST_ASSERT(!ret
&& addr
== expected_addr
, "read characteristics of region #1");
315 addr
= REDIST_REGION_ATTR_ADDR(0, 0, 0, 2);
316 ret
= __kvm_device_attr_get(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
317 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
318 TEST_ASSERT(ret
&& errno
== ENOENT
, "read characteristics of non existing region");
321 kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
322 KVM_VGIC_V3_ADDR_TYPE_DIST
, &addr
);
324 addr
= REDIST_REGION_ATTR_ADDR(1, 0x260000, 0, 2);
325 ret
= __kvm_device_attr_set(v
->gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
326 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
327 TEST_ASSERT(ret
&& errno
== EINVAL
, "register redist region colliding with dist");
331 * VGIC KVM device is created and initialized before the secondary CPUs
334 static void test_vgic_then_vcpus(uint32_t gic_dev_type
)
336 struct kvm_vcpu
*vcpus
[NR_VCPUS
];
340 v
= vm_gic_create_with_vcpus(gic_dev_type
, 1, vcpus
);
342 subtest_dist_rdist(&v
);
344 /* Add the rest of the VCPUs */
345 for (i
= 1; i
< NR_VCPUS
; ++i
)
346 vcpus
[i
] = vm_vcpu_add(v
.vm
, i
, guest_code
);
348 ret
= run_vcpu(vcpus
[3]);
349 TEST_ASSERT(ret
== -EINVAL
, "dist/rdist overlap detected on 1st vcpu run");
354 /* All the VCPUs are created before the VGIC KVM device gets initialized */
355 static void test_vcpus_then_vgic(uint32_t gic_dev_type
)
357 struct kvm_vcpu
*vcpus
[NR_VCPUS
];
361 v
= vm_gic_create_with_vcpus(gic_dev_type
, NR_VCPUS
, vcpus
);
363 subtest_dist_rdist(&v
);
365 ret
= run_vcpu(vcpus
[3]);
366 TEST_ASSERT(ret
== -EINVAL
, "dist/rdist overlap detected on 1st vcpu run");
371 #define KVM_VGIC_V2_ATTR(offset, cpu) \
372 (FIELD_PREP(KVM_DEV_ARM_VGIC_OFFSET_MASK, offset) | \
373 FIELD_PREP(KVM_DEV_ARM_VGIC_CPUID_MASK, cpu))
375 #define GIC_CPU_CTRL 0x00
377 static void test_v2_uaccess_cpuif_no_vcpus(void)
383 v
= vm_gic_create_barebones(KVM_DEV_TYPE_ARM_VGIC_V2
);
384 subtest_dist_rdist(&v
);
386 ret
= __kvm_has_device_attr(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CPU_REGS
,
387 KVM_VGIC_V2_ATTR(GIC_CPU_CTRL
, 0));
388 TEST_ASSERT(ret
&& errno
== EINVAL
,
389 "accessed non-existent CPU interface, want errno: %i",
391 ret
= __kvm_device_attr_get(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CPU_REGS
,
392 KVM_VGIC_V2_ATTR(GIC_CPU_CTRL
, 0), &val
);
393 TEST_ASSERT(ret
&& errno
== EINVAL
,
394 "accessed non-existent CPU interface, want errno: %i",
396 ret
= __kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CPU_REGS
,
397 KVM_VGIC_V2_ATTR(GIC_CPU_CTRL
, 0), &val
);
398 TEST_ASSERT(ret
&& errno
== EINVAL
,
399 "accessed non-existent CPU interface, want errno: %i",
405 static void test_v3_new_redist_regions(void)
407 struct kvm_vcpu
*vcpus
[NR_VCPUS
];
413 v
= vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3
, NR_VCPUS
, vcpus
);
414 subtest_v3_redist_regions(&v
);
415 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CTRL
,
416 KVM_DEV_ARM_VGIC_CTRL_INIT
, NULL
);
418 ret
= run_vcpu(vcpus
[3]);
419 TEST_ASSERT(ret
== -ENXIO
, "running without sufficient number of rdists");
424 v
= vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3
, NR_VCPUS
, vcpus
);
425 subtest_v3_redist_regions(&v
);
427 addr
= REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
428 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
429 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
431 ret
= run_vcpu(vcpus
[3]);
432 TEST_ASSERT(ret
== -EBUSY
, "running without vgic explicit init");
438 v
= vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3
, NR_VCPUS
, vcpus
);
439 subtest_v3_redist_regions(&v
);
441 ret
= __kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
442 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, dummy
);
443 TEST_ASSERT(ret
&& errno
== EFAULT
,
444 "register a third region allowing to cover the 4 vcpus");
446 addr
= REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
447 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
448 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
450 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CTRL
,
451 KVM_DEV_ARM_VGIC_CTRL_INIT
, NULL
);
453 ret
= run_vcpu(vcpus
[3]);
454 TEST_ASSERT(!ret
, "vcpu run");
459 static void test_v3_typer_accesses(void)
465 v
.vm
= vm_create(NR_VCPUS
);
466 (void)vm_vcpu_add(v
.vm
, 0, guest_code
);
468 v
.gic_fd
= kvm_create_device(v
.vm
, KVM_DEV_TYPE_ARM_VGIC_V3
);
470 (void)vm_vcpu_add(v
.vm
, 3, guest_code
);
472 v3_redist_reg_get_errno(v
.gic_fd
, 1, GICR_TYPER
, EINVAL
,
473 "attempting to read GICR_TYPER of non created vcpu");
475 (void)vm_vcpu_add(v
.vm
, 1, guest_code
);
477 v3_redist_reg_get_errno(v
.gic_fd
, 1, GICR_TYPER
, EBUSY
,
478 "read GICR_TYPER before GIC initialized");
480 (void)vm_vcpu_add(v
.vm
, 2, guest_code
);
482 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CTRL
,
483 KVM_DEV_ARM_VGIC_CTRL_INIT
, NULL
);
485 for (i
= 0; i
< NR_VCPUS
; i
++) {
486 v3_redist_reg_get(v
.gic_fd
, i
, GICR_TYPER
, i
* 0x100,
487 "read GICR_TYPER before rdist region setting");
490 addr
= REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
491 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
492 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
494 /* The 2 first rdists should be put there (vcpu 0 and 3) */
495 v3_redist_reg_get(v
.gic_fd
, 0, GICR_TYPER
, 0x0, "read typer of rdist #0");
496 v3_redist_reg_get(v
.gic_fd
, 3, GICR_TYPER
, 0x310, "read typer of rdist #1");
498 addr
= REDIST_REGION_ATTR_ADDR(10, 0x100000, 0, 1);
499 ret
= __kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
500 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
501 TEST_ASSERT(ret
&& errno
== EINVAL
, "collision with previous rdist region");
503 v3_redist_reg_get(v
.gic_fd
, 1, GICR_TYPER
, 0x100,
504 "no redist region attached to vcpu #1 yet, last cannot be returned");
505 v3_redist_reg_get(v
.gic_fd
, 2, GICR_TYPER
, 0x200,
506 "no redist region attached to vcpu #2, last cannot be returned");
508 addr
= REDIST_REGION_ATTR_ADDR(10, 0x20000, 0, 1);
509 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
510 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
512 v3_redist_reg_get(v
.gic_fd
, 1, GICR_TYPER
, 0x100, "read typer of rdist #1");
513 v3_redist_reg_get(v
.gic_fd
, 2, GICR_TYPER
, 0x210,
514 "read typer of rdist #1, last properly returned");
519 static struct vm_gic
vm_gic_v3_create_with_vcpuids(int nr_vcpus
,
525 v
.vm
= vm_create(nr_vcpus
);
526 for (i
= 0; i
< nr_vcpus
; i
++)
527 vm_vcpu_add(v
.vm
, vcpuids
[i
], guest_code
);
529 v
.gic_fd
= kvm_create_device(v
.vm
, KVM_DEV_TYPE_ARM_VGIC_V3
);
535 * Test GICR_TYPER last bit with new redist regions
536 * rdist regions #1 and #2 are contiguous
537 * rdist region #0 @0x100000 2 rdist capacity
538 * rdists: 0, 3 (Last)
539 * rdist region #1 @0x240000 2 rdist capacity
540 * rdists: 5, 4 (Last)
541 * rdist region #2 @0x200000 2 rdist capacity
544 static void test_v3_last_bit_redist_regions(void)
546 uint32_t vcpuids
[] = { 0, 3, 5, 4, 1, 2 };
550 v
= vm_gic_v3_create_with_vcpuids(ARRAY_SIZE(vcpuids
), vcpuids
);
552 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CTRL
,
553 KVM_DEV_ARM_VGIC_CTRL_INIT
, NULL
);
555 addr
= REDIST_REGION_ATTR_ADDR(2, 0x100000, 0, 0);
556 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
557 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
559 addr
= REDIST_REGION_ATTR_ADDR(2, 0x240000, 0, 1);
560 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
561 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
563 addr
= REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 2);
564 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
565 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION
, &addr
);
567 v3_redist_reg_get(v
.gic_fd
, 0, GICR_TYPER
, 0x000, "read typer of rdist #0");
568 v3_redist_reg_get(v
.gic_fd
, 1, GICR_TYPER
, 0x100, "read typer of rdist #1");
569 v3_redist_reg_get(v
.gic_fd
, 2, GICR_TYPER
, 0x200, "read typer of rdist #2");
570 v3_redist_reg_get(v
.gic_fd
, 3, GICR_TYPER
, 0x310, "read typer of rdist #3");
571 v3_redist_reg_get(v
.gic_fd
, 5, GICR_TYPER
, 0x500, "read typer of rdist #5");
572 v3_redist_reg_get(v
.gic_fd
, 4, GICR_TYPER
, 0x410, "read typer of rdist #4");
577 /* Test last bit with legacy region */
578 static void test_v3_last_bit_single_rdist(void)
580 uint32_t vcpuids
[] = { 0, 3, 5, 4, 1, 2 };
584 v
= vm_gic_v3_create_with_vcpuids(ARRAY_SIZE(vcpuids
), vcpuids
);
586 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CTRL
,
587 KVM_DEV_ARM_VGIC_CTRL_INIT
, NULL
);
590 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
591 KVM_VGIC_V3_ADDR_TYPE_REDIST
, &addr
);
593 v3_redist_reg_get(v
.gic_fd
, 0, GICR_TYPER
, 0x000, "read typer of rdist #0");
594 v3_redist_reg_get(v
.gic_fd
, 3, GICR_TYPER
, 0x300, "read typer of rdist #1");
595 v3_redist_reg_get(v
.gic_fd
, 5, GICR_TYPER
, 0x500, "read typer of rdist #2");
596 v3_redist_reg_get(v
.gic_fd
, 1, GICR_TYPER
, 0x100, "read typer of rdist #3");
597 v3_redist_reg_get(v
.gic_fd
, 2, GICR_TYPER
, 0x210, "read typer of rdist #3");
602 /* Uses the legacy REDIST region API. */
603 static void test_v3_redist_ipa_range_check_at_vcpu_run(void)
605 struct kvm_vcpu
*vcpus
[NR_VCPUS
];
610 v
= vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3
, 1, vcpus
);
612 /* Set space for 3 redists, we have 1 vcpu, so this succeeds. */
613 addr
= max_phys_size
- (3 * 2 * 0x10000);
614 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
615 KVM_VGIC_V3_ADDR_TYPE_REDIST
, &addr
);
618 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
619 KVM_VGIC_V3_ADDR_TYPE_DIST
, &addr
);
621 /* Add the rest of the VCPUs */
622 for (i
= 1; i
< NR_VCPUS
; ++i
)
623 vcpus
[i
] = vm_vcpu_add(v
.vm
, i
, guest_code
);
625 kvm_device_attr_set(v
.gic_fd
, KVM_DEV_ARM_VGIC_GRP_CTRL
,
626 KVM_DEV_ARM_VGIC_CTRL_INIT
, NULL
);
628 /* Attempt to run a vcpu without enough redist space. */
629 ret
= run_vcpu(vcpus
[2]);
630 TEST_ASSERT(ret
&& errno
== EINVAL
,
631 "redist base+size above PA range detected on 1st vcpu run");
636 static void test_v3_its_region(void)
638 struct kvm_vcpu
*vcpus
[NR_VCPUS
];
643 v
= vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3
, NR_VCPUS
, vcpus
);
644 its_fd
= kvm_create_device(v
.vm
, KVM_DEV_TYPE_ARM_VGIC_ITS
);
647 ret
= __kvm_device_attr_set(its_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
648 KVM_VGIC_ITS_ADDR_TYPE
, &addr
);
649 TEST_ASSERT(ret
&& errno
== EINVAL
,
650 "ITS region with misaligned address");
652 addr
= max_phys_size
;
653 ret
= __kvm_device_attr_set(its_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
654 KVM_VGIC_ITS_ADDR_TYPE
, &addr
);
655 TEST_ASSERT(ret
&& errno
== E2BIG
,
656 "register ITS region with base address beyond IPA range");
658 addr
= max_phys_size
- 0x10000;
659 ret
= __kvm_device_attr_set(its_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
660 KVM_VGIC_ITS_ADDR_TYPE
, &addr
);
661 TEST_ASSERT(ret
&& errno
== E2BIG
,
662 "Half of ITS region is beyond IPA range");
664 /* This one succeeds setting the ITS base */
666 kvm_device_attr_set(its_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
667 KVM_VGIC_ITS_ADDR_TYPE
, &addr
);
670 ret
= __kvm_device_attr_set(its_fd
, KVM_DEV_ARM_VGIC_GRP_ADDR
,
671 KVM_VGIC_ITS_ADDR_TYPE
, &addr
);
672 TEST_ASSERT(ret
&& errno
== EEXIST
, "ITS base set again");
679 * Returns 0 if it's possible to create GIC device of a given type (V2 or V3).
681 int test_kvm_device(uint32_t gic_dev_type
)
683 struct kvm_vcpu
*vcpus
[NR_VCPUS
];
688 v
.vm
= vm_create_with_vcpus(NR_VCPUS
, guest_code
, vcpus
);
690 /* try to create a non existing KVM device */
691 ret
= __kvm_test_create_device(v
.vm
, 0);
692 TEST_ASSERT(ret
&& errno
== ENODEV
, "unsupported device");
695 ret
= __kvm_test_create_device(v
.vm
, gic_dev_type
);
698 v
.gic_fd
= kvm_create_device(v
.vm
, gic_dev_type
);
700 ret
= __kvm_create_device(v
.vm
, gic_dev_type
);
701 TEST_ASSERT(ret
< 0 && errno
== EEXIST
, "create GIC device twice");
703 /* try to create the other gic_dev_type */
704 other
= VGIC_DEV_IS_V2(gic_dev_type
) ? KVM_DEV_TYPE_ARM_VGIC_V3
705 : KVM_DEV_TYPE_ARM_VGIC_V2
;
707 if (!__kvm_test_create_device(v
.vm
, other
)) {
708 ret
= __kvm_create_device(v
.vm
, other
);
709 TEST_ASSERT(ret
< 0 && (errno
== EINVAL
|| errno
== EEXIST
),
710 "create GIC device while other version exists");
718 void run_tests(uint32_t gic_dev_type
)
720 test_vcpus_then_vgic(gic_dev_type
);
721 test_vgic_then_vcpus(gic_dev_type
);
723 if (VGIC_DEV_IS_V2(gic_dev_type
))
724 test_v2_uaccess_cpuif_no_vcpus();
726 if (VGIC_DEV_IS_V3(gic_dev_type
)) {
727 test_v3_new_redist_regions();
728 test_v3_typer_accesses();
729 test_v3_last_bit_redist_regions();
730 test_v3_last_bit_single_rdist();
731 test_v3_redist_ipa_range_check_at_vcpu_run();
732 test_v3_its_region();
736 int main(int ac
, char **av
)
742 pa_bits
= vm_guest_mode_params
[VM_MODE_DEFAULT
].pa_bits
;
743 max_phys_size
= 1ULL << pa_bits
;
745 ret
= test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V3
);
747 pr_info("Running GIC_v3 tests.\n");
748 run_tests(KVM_DEV_TYPE_ARM_VGIC_V3
);
752 ret
= test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V2
);
754 pr_info("Running GIC_v2 tests.\n");
755 run_tests(KVM_DEV_TYPE_ARM_VGIC_V2
);
760 print_skip("No GICv2 nor GICv3 support");