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