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 #include "vgic.h"
17
18 #define NR_VCPUS 4
19
20 #define REG_OFFSET(vcpu, offset) (((uint64_t)vcpu << 32) | offset)
21
22 #define GICR_TYPER 0x8
23
24 #define VGIC_DEV_IS_V2(_d) ((_d) == KVM_DEV_TYPE_ARM_VGIC_V2)
25 #define VGIC_DEV_IS_V3(_d) ((_d) == KVM_DEV_TYPE_ARM_VGIC_V3)
26
27 struct vm_gic {
28 struct kvm_vm *vm;
29 int gic_fd;
30 uint32_t gic_dev_type;
31 };
32
33 static uint64_t max_phys_size;
34
35 /* helper to access a redistributor register */
access_v3_redist_reg(int gicv3_fd,int vcpu,int offset,uint32_t * val,bool write)36 static int access_v3_redist_reg(int gicv3_fd, int vcpu, int offset,
37 uint32_t *val, bool write)
38 {
39 uint64_t attr = REG_OFFSET(vcpu, offset);
40
41 return _kvm_device_access(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
42 attr, val, write);
43 }
44
45 /* dummy guest code */
guest_code(void)46 static void guest_code(void)
47 {
48 GUEST_SYNC(0);
49 GUEST_SYNC(1);
50 GUEST_SYNC(2);
51 GUEST_DONE();
52 }
53
54 /* we don't want to assert on run execution, hence that helper */
run_vcpu(struct kvm_vm * vm,uint32_t vcpuid)55 static int run_vcpu(struct kvm_vm *vm, uint32_t vcpuid)
56 {
57 ucall_init(vm, NULL);
58 int ret = _vcpu_ioctl(vm, vcpuid, KVM_RUN, NULL);
59 if (ret)
60 return -errno;
61 return 0;
62 }
63
vm_gic_create_with_vcpus(uint32_t gic_dev_type,uint32_t nr_vcpus)64 static struct vm_gic vm_gic_create_with_vcpus(uint32_t gic_dev_type, uint32_t nr_vcpus)
65 {
66 struct vm_gic v;
67
68 v.gic_dev_type = gic_dev_type;
69 v.vm = vm_create_default_with_vcpus(nr_vcpus, 0, 0, guest_code, NULL);
70 v.gic_fd = kvm_create_device(v.vm, gic_dev_type, false);
71
72 return v;
73 }
74
vm_gic_destroy(struct vm_gic * v)75 static void vm_gic_destroy(struct vm_gic *v)
76 {
77 close(v->gic_fd);
78 kvm_vm_free(v->vm);
79 }
80
81 struct vgic_region_attr {
82 uint64_t attr;
83 uint64_t size;
84 uint64_t alignment;
85 };
86
87 struct vgic_region_attr gic_v3_dist_region = {
88 .attr = KVM_VGIC_V3_ADDR_TYPE_DIST,
89 .size = 0x10000,
90 .alignment = 0x10000,
91 };
92
93 struct vgic_region_attr gic_v3_redist_region = {
94 .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST,
95 .size = NR_VCPUS * 0x20000,
96 .alignment = 0x10000,
97 };
98
99 struct vgic_region_attr gic_v2_dist_region = {
100 .attr = KVM_VGIC_V2_ADDR_TYPE_DIST,
101 .size = 0x1000,
102 .alignment = 0x1000,
103 };
104
105 struct vgic_region_attr gic_v2_cpu_region = {
106 .attr = KVM_VGIC_V2_ADDR_TYPE_CPU,
107 .size = 0x2000,
108 .alignment = 0x1000,
109 };
110
111 /**
112 * Helper routine that performs KVM device tests in general. Eventually the
113 * ARM_VGIC (GICv2 or GICv3) device gets created with an overlapping
114 * DIST/REDIST (or DIST/CPUIF for GICv2). Assumption is 4 vcpus are going to be
115 * used hence the overlap. In the case of GICv3, A RDIST region is set at @0x0
116 * and a DIST region is set @0x70000. The GICv2 case sets a CPUIF @0x0 and a
117 * DIST region @0x1000.
118 */
subtest_dist_rdist(struct vm_gic * v)119 static void subtest_dist_rdist(struct vm_gic *v)
120 {
121 int ret;
122 uint64_t addr;
123 struct vgic_region_attr rdist; /* CPU interface in GICv2*/
124 struct vgic_region_attr dist;
125
126 rdist = VGIC_DEV_IS_V3(v->gic_dev_type) ? gic_v3_redist_region
127 : gic_v2_cpu_region;
128 dist = VGIC_DEV_IS_V3(v->gic_dev_type) ? gic_v3_dist_region
129 : gic_v2_dist_region;
130
131 /* Check existing group/attributes */
132 kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
133 dist.attr);
134
135 kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
136 rdist.attr);
137
138 /* check non existing attribute */
139 ret = _kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, -1);
140 TEST_ASSERT(ret && errno == ENXIO, "attribute not supported");
141
142 /* misaligned DIST and REDIST address settings */
143 addr = dist.alignment / 0x10;
144 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
145 dist.attr, &addr, true);
146 TEST_ASSERT(ret && errno == EINVAL, "GIC dist base not aligned");
147
148 addr = rdist.alignment / 0x10;
149 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
150 rdist.attr, &addr, true);
151 TEST_ASSERT(ret && errno == EINVAL, "GIC redist/cpu base not aligned");
152
153 /* out of range address */
154 addr = max_phys_size;
155 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
156 dist.attr, &addr, true);
157 TEST_ASSERT(ret && errno == E2BIG, "dist address beyond IPA limit");
158
159 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
160 rdist.attr, &addr, true);
161 TEST_ASSERT(ret && errno == E2BIG, "redist address beyond IPA limit");
162
163 /* Space for half a rdist (a rdist is: 2 * rdist.alignment). */
164 addr = max_phys_size - dist.alignment;
165 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
166 rdist.attr, &addr, true);
167 TEST_ASSERT(ret && errno == E2BIG,
168 "half of the redist is beyond IPA limit");
169
170 /* set REDIST base address @0x0*/
171 addr = 0x00000;
172 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
173 rdist.attr, &addr, true);
174
175 /* Attempt to create a second legacy redistributor region */
176 addr = 0xE0000;
177 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
178 rdist.attr, &addr, true);
179 TEST_ASSERT(ret && errno == EEXIST, "GIC redist base set again");
180
181 ret = _kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
182 KVM_VGIC_V3_ADDR_TYPE_REDIST);
183 if (!ret) {
184 /* Attempt to mix legacy and new redistributor regions */
185 addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 0, 0);
186 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
187 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION,
188 &addr, true);
189 TEST_ASSERT(ret && errno == EINVAL,
190 "attempt to mix GICv3 REDIST and REDIST_REGION");
191 }
192
193 /*
194 * Set overlapping DIST / REDIST, cannot be detected here. Will be detected
195 * on first vcpu run instead.
196 */
197 addr = rdist.size - rdist.alignment;
198 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
199 dist.attr, &addr, true);
200 }
201
202 /* Test the new REDIST region API */
subtest_v3_redist_regions(struct vm_gic * v)203 static void subtest_v3_redist_regions(struct vm_gic *v)
204 {
205 uint64_t addr, expected_addr;
206 int ret;
207
208 ret = kvm_device_check_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
209 KVM_VGIC_V3_ADDR_TYPE_REDIST);
210 TEST_ASSERT(!ret, "Multiple redist regions advertised");
211
212 addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 2, 0);
213 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
214 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
215 TEST_ASSERT(ret && errno == EINVAL, "redist region attr value with flags != 0");
216
217 addr = REDIST_REGION_ATTR_ADDR(0, 0x100000, 0, 0);
218 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
219 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
220 TEST_ASSERT(ret && errno == EINVAL, "redist region attr value with count== 0");
221
222 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
223 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
224 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
225 TEST_ASSERT(ret && errno == EINVAL,
226 "attempt to register the first rdist region with index != 0");
227
228 addr = REDIST_REGION_ATTR_ADDR(2, 0x201000, 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, true);
231 TEST_ASSERT(ret && errno == EINVAL, "rdist region with misaligned address");
232
233 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
234 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
235 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
236
237 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
238 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
239 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
240 TEST_ASSERT(ret && errno == EINVAL, "register an rdist region with already used index");
241
242 addr = REDIST_REGION_ATTR_ADDR(1, 0x210000, 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,
246 "register an rdist region overlapping with another one");
247
248 addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 2);
249 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
250 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
251 TEST_ASSERT(ret && errno == EINVAL, "register redist region with index not +1");
252
253 addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
254 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
255 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
256
257 addr = REDIST_REGION_ATTR_ADDR(1, max_phys_size, 0, 2);
258 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
259 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
260 TEST_ASSERT(ret && errno == E2BIG,
261 "register redist region with base address beyond IPA range");
262
263 /* The last redist is above the pa range. */
264 addr = REDIST_REGION_ATTR_ADDR(2, max_phys_size - 0x30000, 0, 2);
265 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
266 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
267 TEST_ASSERT(ret && errno == E2BIG,
268 "register redist region with top address beyond IPA range");
269
270 addr = 0x260000;
271 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
272 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
273 TEST_ASSERT(ret && errno == EINVAL,
274 "Mix KVM_VGIC_V3_ADDR_TYPE_REDIST and REDIST_REGION");
275
276 /*
277 * Now there are 2 redist regions:
278 * region 0 @ 0x200000 2 redists
279 * region 1 @ 0x240000 1 redist
280 * Attempt to read their characteristics
281 */
282
283 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 0);
284 expected_addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
285 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
286 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false);
287 TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #0");
288
289 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 1);
290 expected_addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
291 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
292 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false);
293 TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #1");
294
295 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 2);
296 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
297 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, false);
298 TEST_ASSERT(ret && errno == ENOENT, "read characteristics of non existing region");
299
300 addr = 0x260000;
301 kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
302 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true);
303
304 addr = REDIST_REGION_ATTR_ADDR(1, 0x260000, 0, 2);
305 ret = _kvm_device_access(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
306 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
307 TEST_ASSERT(ret && errno == EINVAL, "register redist region colliding with dist");
308 }
309
310 /*
311 * VGIC KVM device is created and initialized before the secondary CPUs
312 * get created
313 */
test_vgic_then_vcpus(uint32_t gic_dev_type)314 static void test_vgic_then_vcpus(uint32_t gic_dev_type)
315 {
316 struct vm_gic v;
317 int ret, i;
318
319 v = vm_gic_create_with_vcpus(gic_dev_type, 1);
320
321 subtest_dist_rdist(&v);
322
323 /* Add the rest of the VCPUs */
324 for (i = 1; i < NR_VCPUS; ++i)
325 vm_vcpu_add_default(v.vm, i, guest_code);
326
327 ret = run_vcpu(v.vm, 3);
328 TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run");
329
330 vm_gic_destroy(&v);
331 }
332
333 /* All the VCPUs are created before the VGIC KVM device gets initialized */
test_vcpus_then_vgic(uint32_t gic_dev_type)334 static void test_vcpus_then_vgic(uint32_t gic_dev_type)
335 {
336 struct vm_gic v;
337 int ret;
338
339 v = vm_gic_create_with_vcpus(gic_dev_type, NR_VCPUS);
340
341 subtest_dist_rdist(&v);
342
343 ret = run_vcpu(v.vm, 3);
344 TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run");
345
346 vm_gic_destroy(&v);
347 }
348
test_v3_new_redist_regions(void)349 static void test_v3_new_redist_regions(void)
350 {
351 void *dummy = NULL;
352 struct vm_gic v;
353 uint64_t addr;
354 int ret;
355
356 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS);
357 subtest_v3_redist_regions(&v);
358 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
359 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
360
361 ret = run_vcpu(v.vm, 3);
362 TEST_ASSERT(ret == -ENXIO, "running without sufficient number of rdists");
363 vm_gic_destroy(&v);
364
365 /* step2 */
366
367 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS);
368 subtest_v3_redist_regions(&v);
369
370 addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
371 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
372 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
373
374 ret = run_vcpu(v.vm, 3);
375 TEST_ASSERT(ret == -EBUSY, "running without vgic explicit init");
376
377 vm_gic_destroy(&v);
378
379 /* step 3 */
380
381 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS);
382 subtest_v3_redist_regions(&v);
383
384 _kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
385 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, dummy, true);
386 TEST_ASSERT(ret && errno == EFAULT,
387 "register a third region allowing to cover the 4 vcpus");
388
389 addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
390 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
391 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
392
393 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
394 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
395
396 ret = run_vcpu(v.vm, 3);
397 TEST_ASSERT(!ret, "vcpu run");
398
399 vm_gic_destroy(&v);
400 }
401
test_v3_typer_accesses(void)402 static void test_v3_typer_accesses(void)
403 {
404 struct vm_gic v;
405 uint64_t addr;
406 uint32_t val;
407 int ret, i;
408
409 v.vm = vm_create_default(0, 0, guest_code);
410
411 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
412
413 vm_vcpu_add_default(v.vm, 3, guest_code);
414
415 ret = access_v3_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
416 TEST_ASSERT(ret && errno == EINVAL, "attempting to read GICR_TYPER of non created vcpu");
417
418 vm_vcpu_add_default(v.vm, 1, guest_code);
419
420 ret = access_v3_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
421 TEST_ASSERT(ret && errno == EBUSY, "read GICR_TYPER before GIC initialized");
422
423 vm_vcpu_add_default(v.vm, 2, guest_code);
424
425 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
426 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
427
428 for (i = 0; i < NR_VCPUS ; i++) {
429 ret = access_v3_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
430 TEST_ASSERT(!ret && !val, "read GICR_TYPER before rdist region setting");
431 }
432
433 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
434 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
435 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
436
437 /* The 2 first rdists should be put there (vcpu 0 and 3) */
438 ret = access_v3_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
439 TEST_ASSERT(!ret && !val, "read typer of rdist #0");
440
441 ret = access_v3_redist_reg(v.gic_fd, 3, GICR_TYPER, &val, false);
442 TEST_ASSERT(!ret && val == 0x310, "read typer of rdist #1");
443
444 addr = REDIST_REGION_ATTR_ADDR(10, 0x100000, 0, 1);
445 ret = _kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
446 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
447 TEST_ASSERT(ret && errno == EINVAL, "collision with previous rdist region");
448
449 ret = access_v3_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
450 TEST_ASSERT(!ret && val == 0x100,
451 "no redist region attached to vcpu #1 yet, last cannot be returned");
452
453 ret = access_v3_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
454 TEST_ASSERT(!ret && val == 0x200,
455 "no redist region attached to vcpu #2, last cannot be returned");
456
457 addr = REDIST_REGION_ATTR_ADDR(10, 0x20000, 0, 1);
458 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
459 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
460
461 ret = access_v3_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
462 TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1");
463
464 ret = access_v3_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
465 TEST_ASSERT(!ret && val == 0x210,
466 "read typer of rdist #1, last properly returned");
467
468 vm_gic_destroy(&v);
469 }
470
471 /**
472 * Test GICR_TYPER last bit with new redist regions
473 * rdist regions #1 and #2 are contiguous
474 * rdist region #0 @0x100000 2 rdist capacity
475 * rdists: 0, 3 (Last)
476 * rdist region #1 @0x240000 2 rdist capacity
477 * rdists: 5, 4 (Last)
478 * rdist region #2 @0x200000 2 rdist capacity
479 * rdists: 1, 2
480 */
test_v3_last_bit_redist_regions(void)481 static void test_v3_last_bit_redist_regions(void)
482 {
483 uint32_t vcpuids[] = { 0, 3, 5, 4, 1, 2 };
484 struct vm_gic v;
485 uint64_t addr;
486 uint32_t val;
487 int ret;
488
489 v.vm = vm_create_default_with_vcpus(6, 0, 0, guest_code, vcpuids);
490
491 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
492
493 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
494 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
495
496 addr = REDIST_REGION_ATTR_ADDR(2, 0x100000, 0, 0);
497 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
498 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
499
500 addr = REDIST_REGION_ATTR_ADDR(2, 0x240000, 0, 1);
501 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
502 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
503
504 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 2);
505 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
506 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr, true);
507
508 ret = access_v3_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
509 TEST_ASSERT(!ret && val == 0x000, "read typer of rdist #0");
510
511 ret = access_v3_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
512 TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #1");
513
514 ret = access_v3_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
515 TEST_ASSERT(!ret && val == 0x200, "read typer of rdist #2");
516
517 ret = access_v3_redist_reg(v.gic_fd, 3, GICR_TYPER, &val, false);
518 TEST_ASSERT(!ret && val == 0x310, "read typer of rdist #3");
519
520 ret = access_v3_redist_reg(v.gic_fd, 5, GICR_TYPER, &val, false);
521 TEST_ASSERT(!ret && val == 0x500, "read typer of rdist #5");
522
523 ret = access_v3_redist_reg(v.gic_fd, 4, GICR_TYPER, &val, false);
524 TEST_ASSERT(!ret && val == 0x410, "read typer of rdist #4");
525
526 vm_gic_destroy(&v);
527 }
528
529 /* Test last bit with legacy region */
test_v3_last_bit_single_rdist(void)530 static void test_v3_last_bit_single_rdist(void)
531 {
532 uint32_t vcpuids[] = { 0, 3, 5, 4, 1, 2 };
533 struct vm_gic v;
534 uint64_t addr;
535 uint32_t val;
536 int ret;
537
538 v.vm = vm_create_default_with_vcpus(6, 0, 0, guest_code, vcpuids);
539
540 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3, false);
541
542 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
543 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
544
545 addr = 0x10000;
546 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
547 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
548
549 ret = access_v3_redist_reg(v.gic_fd, 0, GICR_TYPER, &val, false);
550 TEST_ASSERT(!ret && val == 0x000, "read typer of rdist #0");
551
552 ret = access_v3_redist_reg(v.gic_fd, 3, GICR_TYPER, &val, false);
553 TEST_ASSERT(!ret && val == 0x300, "read typer of rdist #1");
554
555 ret = access_v3_redist_reg(v.gic_fd, 5, GICR_TYPER, &val, false);
556 TEST_ASSERT(!ret && val == 0x500, "read typer of rdist #2");
557
558 ret = access_v3_redist_reg(v.gic_fd, 1, GICR_TYPER, &val, false);
559 TEST_ASSERT(!ret && val == 0x100, "read typer of rdist #3");
560
561 ret = access_v3_redist_reg(v.gic_fd, 2, GICR_TYPER, &val, false);
562 TEST_ASSERT(!ret && val == 0x210, "read typer of rdist #3");
563
564 vm_gic_destroy(&v);
565 }
566
567 /* Uses the legacy REDIST region API. */
test_v3_redist_ipa_range_check_at_vcpu_run(void)568 static void test_v3_redist_ipa_range_check_at_vcpu_run(void)
569 {
570 struct vm_gic v;
571 int ret, i;
572 uint64_t addr;
573
574 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, 1);
575
576 /* Set space for 3 redists, we have 1 vcpu, so this succeeds. */
577 addr = max_phys_size - (3 * 2 * 0x10000);
578 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
579 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr, true);
580
581 addr = 0x00000;
582 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
583 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr, true);
584
585 /* Add the rest of the VCPUs */
586 for (i = 1; i < NR_VCPUS; ++i)
587 vm_vcpu_add_default(v.vm, i, guest_code);
588
589 kvm_device_access(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
590 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
591
592 /* Attempt to run a vcpu without enough redist space. */
593 ret = run_vcpu(v.vm, 2);
594 TEST_ASSERT(ret && errno == EINVAL,
595 "redist base+size above PA range detected on 1st vcpu run");
596
597 vm_gic_destroy(&v);
598 }
599
test_v3_its_region(void)600 static void test_v3_its_region(void)
601 {
602 struct vm_gic v;
603 uint64_t addr;
604 int its_fd, ret;
605
606 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS);
607 its_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_ITS, false);
608
609 addr = 0x401000;
610 ret = _kvm_device_access(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
611 KVM_VGIC_ITS_ADDR_TYPE, &addr, true);
612 TEST_ASSERT(ret && errno == EINVAL,
613 "ITS region with misaligned address");
614
615 addr = max_phys_size;
616 ret = _kvm_device_access(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
617 KVM_VGIC_ITS_ADDR_TYPE, &addr, true);
618 TEST_ASSERT(ret && errno == E2BIG,
619 "register ITS region with base address beyond IPA range");
620
621 addr = max_phys_size - 0x10000;
622 ret = _kvm_device_access(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
623 KVM_VGIC_ITS_ADDR_TYPE, &addr, true);
624 TEST_ASSERT(ret && errno == E2BIG,
625 "Half of ITS region is beyond IPA range");
626
627 /* This one succeeds setting the ITS base */
628 addr = 0x400000;
629 kvm_device_access(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
630 KVM_VGIC_ITS_ADDR_TYPE, &addr, true);
631
632 addr = 0x300000;
633 ret = _kvm_device_access(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
634 KVM_VGIC_ITS_ADDR_TYPE, &addr, true);
635 TEST_ASSERT(ret && errno == EEXIST, "ITS base set again");
636
637 close(its_fd);
638 vm_gic_destroy(&v);
639 }
640
641 /*
642 * Returns 0 if it's possible to create GIC device of a given type (V2 or V3).
643 */
test_kvm_device(uint32_t gic_dev_type)644 int test_kvm_device(uint32_t gic_dev_type)
645 {
646 struct vm_gic v;
647 int ret, fd;
648 uint32_t other;
649
650 v.vm = vm_create_default_with_vcpus(NR_VCPUS, 0, 0, guest_code, NULL);
651
652 /* try to create a non existing KVM device */
653 ret = _kvm_create_device(v.vm, 0, true, &fd);
654 TEST_ASSERT(ret && errno == ENODEV, "unsupported device");
655
656 /* trial mode */
657 ret = _kvm_create_device(v.vm, gic_dev_type, true, &fd);
658 if (ret)
659 return ret;
660 v.gic_fd = kvm_create_device(v.vm, gic_dev_type, false);
661
662 ret = _kvm_create_device(v.vm, gic_dev_type, false, &fd);
663 TEST_ASSERT(ret && errno == EEXIST, "create GIC device twice");
664
665 kvm_create_device(v.vm, gic_dev_type, true);
666
667 /* try to create the other gic_dev_type */
668 other = VGIC_DEV_IS_V2(gic_dev_type) ? KVM_DEV_TYPE_ARM_VGIC_V3
669 : KVM_DEV_TYPE_ARM_VGIC_V2;
670
671 if (!_kvm_create_device(v.vm, other, true, &fd)) {
672 ret = _kvm_create_device(v.vm, other, false, &fd);
673 TEST_ASSERT(ret && errno == EINVAL,
674 "create GIC device while other version exists");
675 }
676
677 vm_gic_destroy(&v);
678
679 return 0;
680 }
681
run_tests(uint32_t gic_dev_type)682 void run_tests(uint32_t gic_dev_type)
683 {
684 test_vcpus_then_vgic(gic_dev_type);
685 test_vgic_then_vcpus(gic_dev_type);
686
687 if (VGIC_DEV_IS_V3(gic_dev_type)) {
688 test_v3_new_redist_regions();
689 test_v3_typer_accesses();
690 test_v3_last_bit_redist_regions();
691 test_v3_last_bit_single_rdist();
692 test_v3_redist_ipa_range_check_at_vcpu_run();
693 test_v3_its_region();
694 }
695 }
696
main(int ac,char ** av)697 int main(int ac, char **av)
698 {
699 int ret;
700 int pa_bits;
701
702 pa_bits = vm_guest_mode_params[VM_MODE_DEFAULT].pa_bits;
703 max_phys_size = 1ULL << pa_bits;
704
705 ret = test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V3);
706 if (!ret) {
707 pr_info("Running GIC_v3 tests.\n");
708 run_tests(KVM_DEV_TYPE_ARM_VGIC_V3);
709 return 0;
710 }
711
712 ret = test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V2);
713 if (!ret) {
714 pr_info("Running GIC_v2 tests.\n");
715 run_tests(KVM_DEV_TYPE_ARM_VGIC_V2);
716 return 0;
717 }
718
719 print_skip("No GICv2 nor GICv3 support");
720 exit(KSFT_SKIP);
721 return 0;
722 }
723