0001
0002
0003
0004
0005
0006
0007 #define _GNU_SOURCE
0008 #include <linux/kernel.h>
0009 #include <sys/syscall.h>
0010 #include <asm/kvm.h>
0011 #include <asm/kvm_para.h>
0012
0013 #include "test_util.h"
0014 #include "kvm_util.h"
0015 #include "processor.h"
0016 #include "vgic.h"
0017
0018 #define NR_VCPUS 4
0019
0020 #define REG_OFFSET(vcpu, offset) (((uint64_t)vcpu << 32) | offset)
0021
0022 #define GICR_TYPER 0x8
0023
0024 #define VGIC_DEV_IS_V2(_d) ((_d) == KVM_DEV_TYPE_ARM_VGIC_V2)
0025 #define VGIC_DEV_IS_V3(_d) ((_d) == KVM_DEV_TYPE_ARM_VGIC_V3)
0026
0027 struct vm_gic {
0028 struct kvm_vm *vm;
0029 int gic_fd;
0030 uint32_t gic_dev_type;
0031 };
0032
0033 static uint64_t max_phys_size;
0034
0035
0036
0037
0038
0039 static void v3_redist_reg_get_errno(int gicv3_fd, int vcpu, int offset,
0040 int want, const char *msg)
0041 {
0042 uint32_t ignored_val;
0043 int ret = __kvm_device_attr_get(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
0044 REG_OFFSET(vcpu, offset), &ignored_val);
0045
0046 TEST_ASSERT(ret && errno == want, "%s; want errno = %d", msg, want);
0047 }
0048
0049 static void v3_redist_reg_get(int gicv3_fd, int vcpu, int offset, uint32_t want,
0050 const char *msg)
0051 {
0052 uint32_t val;
0053
0054 kvm_device_attr_get(gicv3_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
0055 REG_OFFSET(vcpu, offset), &val);
0056 TEST_ASSERT(val == want, "%s; want '0x%x', got '0x%x'", msg, want, val);
0057 }
0058
0059
0060 static void guest_code(void)
0061 {
0062 GUEST_SYNC(0);
0063 GUEST_SYNC(1);
0064 GUEST_SYNC(2);
0065 GUEST_DONE();
0066 }
0067
0068
0069 static int run_vcpu(struct kvm_vcpu *vcpu)
0070 {
0071 ucall_init(vcpu->vm, NULL);
0072
0073 return __vcpu_run(vcpu) ? -errno : 0;
0074 }
0075
0076 static struct vm_gic vm_gic_create_with_vcpus(uint32_t gic_dev_type,
0077 uint32_t nr_vcpus,
0078 struct kvm_vcpu *vcpus[])
0079 {
0080 struct vm_gic v;
0081
0082 v.gic_dev_type = gic_dev_type;
0083 v.vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
0084 v.gic_fd = kvm_create_device(v.vm, gic_dev_type);
0085
0086 return v;
0087 }
0088
0089 static void vm_gic_destroy(struct vm_gic *v)
0090 {
0091 close(v->gic_fd);
0092 kvm_vm_free(v->vm);
0093 }
0094
0095 struct vgic_region_attr {
0096 uint64_t attr;
0097 uint64_t size;
0098 uint64_t alignment;
0099 };
0100
0101 struct vgic_region_attr gic_v3_dist_region = {
0102 .attr = KVM_VGIC_V3_ADDR_TYPE_DIST,
0103 .size = 0x10000,
0104 .alignment = 0x10000,
0105 };
0106
0107 struct vgic_region_attr gic_v3_redist_region = {
0108 .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST,
0109 .size = NR_VCPUS * 0x20000,
0110 .alignment = 0x10000,
0111 };
0112
0113 struct vgic_region_attr gic_v2_dist_region = {
0114 .attr = KVM_VGIC_V2_ADDR_TYPE_DIST,
0115 .size = 0x1000,
0116 .alignment = 0x1000,
0117 };
0118
0119 struct vgic_region_attr gic_v2_cpu_region = {
0120 .attr = KVM_VGIC_V2_ADDR_TYPE_CPU,
0121 .size = 0x2000,
0122 .alignment = 0x1000,
0123 };
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 static void subtest_dist_rdist(struct vm_gic *v)
0134 {
0135 int ret;
0136 uint64_t addr;
0137 struct vgic_region_attr rdist;
0138 struct vgic_region_attr dist;
0139
0140 rdist = VGIC_DEV_IS_V3(v->gic_dev_type) ? gic_v3_redist_region
0141 : gic_v2_cpu_region;
0142 dist = VGIC_DEV_IS_V3(v->gic_dev_type) ? gic_v3_dist_region
0143 : gic_v2_dist_region;
0144
0145
0146 kvm_has_device_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, dist.attr);
0147
0148 kvm_has_device_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, rdist.attr);
0149
0150
0151 ret = __kvm_has_device_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, -1);
0152 TEST_ASSERT(ret && errno == ENXIO, "attribute not supported");
0153
0154
0155 addr = dist.alignment / 0x10;
0156 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0157 dist.attr, &addr);
0158 TEST_ASSERT(ret && errno == EINVAL, "GIC dist base not aligned");
0159
0160 addr = rdist.alignment / 0x10;
0161 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0162 rdist.attr, &addr);
0163 TEST_ASSERT(ret && errno == EINVAL, "GIC redist/cpu base not aligned");
0164
0165
0166 addr = max_phys_size;
0167 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0168 dist.attr, &addr);
0169 TEST_ASSERT(ret && errno == E2BIG, "dist address beyond IPA limit");
0170
0171 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0172 rdist.attr, &addr);
0173 TEST_ASSERT(ret && errno == E2BIG, "redist address beyond IPA limit");
0174
0175
0176 addr = max_phys_size - dist.alignment;
0177 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0178 rdist.attr, &addr);
0179 TEST_ASSERT(ret && errno == E2BIG,
0180 "half of the redist is beyond IPA limit");
0181
0182
0183 addr = 0x00000;
0184 kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0185 rdist.attr, &addr);
0186
0187
0188 addr = 0xE0000;
0189 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0190 rdist.attr, &addr);
0191 TEST_ASSERT(ret && errno == EEXIST, "GIC redist base set again");
0192
0193 ret = __kvm_has_device_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0194 KVM_VGIC_V3_ADDR_TYPE_REDIST);
0195 if (!ret) {
0196
0197 addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 0, 0);
0198 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0199 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0200 TEST_ASSERT(ret && errno == EINVAL,
0201 "attempt to mix GICv3 REDIST and REDIST_REGION");
0202 }
0203
0204
0205
0206
0207
0208 addr = rdist.size - rdist.alignment;
0209 kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0210 dist.attr, &addr);
0211 }
0212
0213
0214 static void subtest_v3_redist_regions(struct vm_gic *v)
0215 {
0216 uint64_t addr, expected_addr;
0217 int ret;
0218
0219 ret = __kvm_has_device_attr(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0220 KVM_VGIC_V3_ADDR_TYPE_REDIST);
0221 TEST_ASSERT(!ret, "Multiple redist regions advertised");
0222
0223 addr = REDIST_REGION_ATTR_ADDR(NR_VCPUS, 0x100000, 2, 0);
0224 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0225 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0226 TEST_ASSERT(ret && errno == EINVAL, "redist region attr value with flags != 0");
0227
0228 addr = REDIST_REGION_ATTR_ADDR(0, 0x100000, 0, 0);
0229 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0230 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0231 TEST_ASSERT(ret && errno == EINVAL, "redist region attr value with count== 0");
0232
0233 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
0234 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0235 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0236 TEST_ASSERT(ret && errno == EINVAL,
0237 "attempt to register the first rdist region with index != 0");
0238
0239 addr = REDIST_REGION_ATTR_ADDR(2, 0x201000, 0, 1);
0240 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0241 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0242 TEST_ASSERT(ret && errno == EINVAL, "rdist region with misaligned address");
0243
0244 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
0245 kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0246 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0247
0248 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 1);
0249 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0250 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0251 TEST_ASSERT(ret && errno == EINVAL, "register an rdist region with already used index");
0252
0253 addr = REDIST_REGION_ATTR_ADDR(1, 0x210000, 0, 2);
0254 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0255 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0256 TEST_ASSERT(ret && errno == EINVAL,
0257 "register an rdist region overlapping with another one");
0258
0259 addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 2);
0260 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0261 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0262 TEST_ASSERT(ret && errno == EINVAL, "register redist region with index not +1");
0263
0264 addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
0265 kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0266 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0267
0268 addr = REDIST_REGION_ATTR_ADDR(1, max_phys_size, 0, 2);
0269 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0270 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0271 TEST_ASSERT(ret && errno == E2BIG,
0272 "register redist region with base address beyond IPA range");
0273
0274
0275 addr = REDIST_REGION_ATTR_ADDR(2, max_phys_size - 0x30000, 0, 2);
0276 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0277 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0278 TEST_ASSERT(ret && errno == E2BIG,
0279 "register redist region with top address beyond IPA range");
0280
0281 addr = 0x260000;
0282 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0283 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr);
0284 TEST_ASSERT(ret && errno == EINVAL,
0285 "Mix KVM_VGIC_V3_ADDR_TYPE_REDIST and REDIST_REGION");
0286
0287
0288
0289
0290
0291
0292
0293
0294 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 0);
0295 expected_addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
0296 ret = __kvm_device_attr_get(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0297 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0298 TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #0");
0299
0300 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 1);
0301 expected_addr = REDIST_REGION_ATTR_ADDR(1, 0x240000, 0, 1);
0302 ret = __kvm_device_attr_get(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0303 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0304 TEST_ASSERT(!ret && addr == expected_addr, "read characteristics of region #1");
0305
0306 addr = REDIST_REGION_ATTR_ADDR(0, 0, 0, 2);
0307 ret = __kvm_device_attr_get(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0308 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0309 TEST_ASSERT(ret && errno == ENOENT, "read characteristics of non existing region");
0310
0311 addr = 0x260000;
0312 kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0313 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr);
0314
0315 addr = REDIST_REGION_ATTR_ADDR(1, 0x260000, 0, 2);
0316 ret = __kvm_device_attr_set(v->gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0317 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0318 TEST_ASSERT(ret && errno == EINVAL, "register redist region colliding with dist");
0319 }
0320
0321
0322
0323
0324
0325 static void test_vgic_then_vcpus(uint32_t gic_dev_type)
0326 {
0327 struct kvm_vcpu *vcpus[NR_VCPUS];
0328 struct vm_gic v;
0329 int ret, i;
0330
0331 v = vm_gic_create_with_vcpus(gic_dev_type, 1, vcpus);
0332
0333 subtest_dist_rdist(&v);
0334
0335
0336 for (i = 1; i < NR_VCPUS; ++i)
0337 vcpus[i] = vm_vcpu_add(v.vm, i, guest_code);
0338
0339 ret = run_vcpu(vcpus[3]);
0340 TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run");
0341
0342 vm_gic_destroy(&v);
0343 }
0344
0345
0346 static void test_vcpus_then_vgic(uint32_t gic_dev_type)
0347 {
0348 struct kvm_vcpu *vcpus[NR_VCPUS];
0349 struct vm_gic v;
0350 int ret;
0351
0352 v = vm_gic_create_with_vcpus(gic_dev_type, NR_VCPUS, vcpus);
0353
0354 subtest_dist_rdist(&v);
0355
0356 ret = run_vcpu(vcpus[3]);
0357 TEST_ASSERT(ret == -EINVAL, "dist/rdist overlap detected on 1st vcpu run");
0358
0359 vm_gic_destroy(&v);
0360 }
0361
0362 static void test_v3_new_redist_regions(void)
0363 {
0364 struct kvm_vcpu *vcpus[NR_VCPUS];
0365 void *dummy = NULL;
0366 struct vm_gic v;
0367 uint64_t addr;
0368 int ret;
0369
0370 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS, vcpus);
0371 subtest_v3_redist_regions(&v);
0372 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
0373 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
0374
0375 ret = run_vcpu(vcpus[3]);
0376 TEST_ASSERT(ret == -ENXIO, "running without sufficient number of rdists");
0377 vm_gic_destroy(&v);
0378
0379
0380
0381 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS, vcpus);
0382 subtest_v3_redist_regions(&v);
0383
0384 addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
0385 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0386 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0387
0388 ret = run_vcpu(vcpus[3]);
0389 TEST_ASSERT(ret == -EBUSY, "running without vgic explicit init");
0390
0391 vm_gic_destroy(&v);
0392
0393
0394
0395 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS, vcpus);
0396 subtest_v3_redist_regions(&v);
0397
0398 ret = __kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0399 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, dummy);
0400 TEST_ASSERT(ret && errno == EFAULT,
0401 "register a third region allowing to cover the 4 vcpus");
0402
0403 addr = REDIST_REGION_ATTR_ADDR(1, 0x280000, 0, 2);
0404 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0405 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0406
0407 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
0408 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
0409
0410 ret = run_vcpu(vcpus[3]);
0411 TEST_ASSERT(!ret, "vcpu run");
0412
0413 vm_gic_destroy(&v);
0414 }
0415
0416 static void test_v3_typer_accesses(void)
0417 {
0418 struct vm_gic v;
0419 uint64_t addr;
0420 int ret, i;
0421
0422 v.vm = vm_create(NR_VCPUS);
0423 (void)vm_vcpu_add(v.vm, 0, guest_code);
0424
0425 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3);
0426
0427 (void)vm_vcpu_add(v.vm, 3, guest_code);
0428
0429 v3_redist_reg_get_errno(v.gic_fd, 1, GICR_TYPER, EINVAL,
0430 "attempting to read GICR_TYPER of non created vcpu");
0431
0432 (void)vm_vcpu_add(v.vm, 1, guest_code);
0433
0434 v3_redist_reg_get_errno(v.gic_fd, 1, GICR_TYPER, EBUSY,
0435 "read GICR_TYPER before GIC initialized");
0436
0437 (void)vm_vcpu_add(v.vm, 2, guest_code);
0438
0439 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
0440 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
0441
0442 for (i = 0; i < NR_VCPUS ; i++) {
0443 v3_redist_reg_get(v.gic_fd, i, GICR_TYPER, i * 0x100,
0444 "read GICR_TYPER before rdist region setting");
0445 }
0446
0447 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 0);
0448 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0449 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0450
0451
0452 v3_redist_reg_get(v.gic_fd, 0, GICR_TYPER, 0x0, "read typer of rdist #0");
0453 v3_redist_reg_get(v.gic_fd, 3, GICR_TYPER, 0x310, "read typer of rdist #1");
0454
0455 addr = REDIST_REGION_ATTR_ADDR(10, 0x100000, 0, 1);
0456 ret = __kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0457 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0458 TEST_ASSERT(ret && errno == EINVAL, "collision with previous rdist region");
0459
0460 v3_redist_reg_get(v.gic_fd, 1, GICR_TYPER, 0x100,
0461 "no redist region attached to vcpu #1 yet, last cannot be returned");
0462 v3_redist_reg_get(v.gic_fd, 2, GICR_TYPER, 0x200,
0463 "no redist region attached to vcpu #2, last cannot be returned");
0464
0465 addr = REDIST_REGION_ATTR_ADDR(10, 0x20000, 0, 1);
0466 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0467 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0468
0469 v3_redist_reg_get(v.gic_fd, 1, GICR_TYPER, 0x100, "read typer of rdist #1");
0470 v3_redist_reg_get(v.gic_fd, 2, GICR_TYPER, 0x210,
0471 "read typer of rdist #1, last properly returned");
0472
0473 vm_gic_destroy(&v);
0474 }
0475
0476 static struct vm_gic vm_gic_v3_create_with_vcpuids(int nr_vcpus,
0477 uint32_t vcpuids[])
0478 {
0479 struct vm_gic v;
0480 int i;
0481
0482 v.vm = vm_create(nr_vcpus);
0483 for (i = 0; i < nr_vcpus; i++)
0484 vm_vcpu_add(v.vm, vcpuids[i], guest_code);
0485
0486 v.gic_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_V3);
0487
0488 return v;
0489 }
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 static void test_v3_last_bit_redist_regions(void)
0502 {
0503 uint32_t vcpuids[] = { 0, 3, 5, 4, 1, 2 };
0504 struct vm_gic v;
0505 uint64_t addr;
0506
0507 v = vm_gic_v3_create_with_vcpuids(ARRAY_SIZE(vcpuids), vcpuids);
0508
0509 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
0510 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
0511
0512 addr = REDIST_REGION_ATTR_ADDR(2, 0x100000, 0, 0);
0513 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0514 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0515
0516 addr = REDIST_REGION_ATTR_ADDR(2, 0x240000, 0, 1);
0517 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0518 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0519
0520 addr = REDIST_REGION_ATTR_ADDR(2, 0x200000, 0, 2);
0521 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0522 KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &addr);
0523
0524 v3_redist_reg_get(v.gic_fd, 0, GICR_TYPER, 0x000, "read typer of rdist #0");
0525 v3_redist_reg_get(v.gic_fd, 1, GICR_TYPER, 0x100, "read typer of rdist #1");
0526 v3_redist_reg_get(v.gic_fd, 2, GICR_TYPER, 0x200, "read typer of rdist #2");
0527 v3_redist_reg_get(v.gic_fd, 3, GICR_TYPER, 0x310, "read typer of rdist #3");
0528 v3_redist_reg_get(v.gic_fd, 5, GICR_TYPER, 0x500, "read typer of rdist #5");
0529 v3_redist_reg_get(v.gic_fd, 4, GICR_TYPER, 0x410, "read typer of rdist #4");
0530
0531 vm_gic_destroy(&v);
0532 }
0533
0534
0535 static void test_v3_last_bit_single_rdist(void)
0536 {
0537 uint32_t vcpuids[] = { 0, 3, 5, 4, 1, 2 };
0538 struct vm_gic v;
0539 uint64_t addr;
0540
0541 v = vm_gic_v3_create_with_vcpuids(ARRAY_SIZE(vcpuids), vcpuids);
0542
0543 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
0544 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
0545
0546 addr = 0x10000;
0547 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0548 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr);
0549
0550 v3_redist_reg_get(v.gic_fd, 0, GICR_TYPER, 0x000, "read typer of rdist #0");
0551 v3_redist_reg_get(v.gic_fd, 3, GICR_TYPER, 0x300, "read typer of rdist #1");
0552 v3_redist_reg_get(v.gic_fd, 5, GICR_TYPER, 0x500, "read typer of rdist #2");
0553 v3_redist_reg_get(v.gic_fd, 1, GICR_TYPER, 0x100, "read typer of rdist #3");
0554 v3_redist_reg_get(v.gic_fd, 2, GICR_TYPER, 0x210, "read typer of rdist #3");
0555
0556 vm_gic_destroy(&v);
0557 }
0558
0559
0560 static void test_v3_redist_ipa_range_check_at_vcpu_run(void)
0561 {
0562 struct kvm_vcpu *vcpus[NR_VCPUS];
0563 struct vm_gic v;
0564 int ret, i;
0565 uint64_t addr;
0566
0567 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, 1, vcpus);
0568
0569
0570 addr = max_phys_size - (3 * 2 * 0x10000);
0571 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0572 KVM_VGIC_V3_ADDR_TYPE_REDIST, &addr);
0573
0574 addr = 0x00000;
0575 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0576 KVM_VGIC_V3_ADDR_TYPE_DIST, &addr);
0577
0578
0579 for (i = 1; i < NR_VCPUS; ++i)
0580 vcpus[i] = vm_vcpu_add(v.vm, i, guest_code);
0581
0582 kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
0583 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
0584
0585
0586 ret = run_vcpu(vcpus[2]);
0587 TEST_ASSERT(ret && errno == EINVAL,
0588 "redist base+size above PA range detected on 1st vcpu run");
0589
0590 vm_gic_destroy(&v);
0591 }
0592
0593 static void test_v3_its_region(void)
0594 {
0595 struct kvm_vcpu *vcpus[NR_VCPUS];
0596 struct vm_gic v;
0597 uint64_t addr;
0598 int its_fd, ret;
0599
0600 v = vm_gic_create_with_vcpus(KVM_DEV_TYPE_ARM_VGIC_V3, NR_VCPUS, vcpus);
0601 its_fd = kvm_create_device(v.vm, KVM_DEV_TYPE_ARM_VGIC_ITS);
0602
0603 addr = 0x401000;
0604 ret = __kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0605 KVM_VGIC_ITS_ADDR_TYPE, &addr);
0606 TEST_ASSERT(ret && errno == EINVAL,
0607 "ITS region with misaligned address");
0608
0609 addr = max_phys_size;
0610 ret = __kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0611 KVM_VGIC_ITS_ADDR_TYPE, &addr);
0612 TEST_ASSERT(ret && errno == E2BIG,
0613 "register ITS region with base address beyond IPA range");
0614
0615 addr = max_phys_size - 0x10000;
0616 ret = __kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0617 KVM_VGIC_ITS_ADDR_TYPE, &addr);
0618 TEST_ASSERT(ret && errno == E2BIG,
0619 "Half of ITS region is beyond IPA range");
0620
0621
0622 addr = 0x400000;
0623 kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0624 KVM_VGIC_ITS_ADDR_TYPE, &addr);
0625
0626 addr = 0x300000;
0627 ret = __kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
0628 KVM_VGIC_ITS_ADDR_TYPE, &addr);
0629 TEST_ASSERT(ret && errno == EEXIST, "ITS base set again");
0630
0631 close(its_fd);
0632 vm_gic_destroy(&v);
0633 }
0634
0635
0636
0637
0638 int test_kvm_device(uint32_t gic_dev_type)
0639 {
0640 struct kvm_vcpu *vcpus[NR_VCPUS];
0641 struct vm_gic v;
0642 uint32_t other;
0643 int ret;
0644
0645 v.vm = vm_create_with_vcpus(NR_VCPUS, guest_code, vcpus);
0646
0647
0648 ret = __kvm_test_create_device(v.vm, 0);
0649 TEST_ASSERT(ret && errno == ENODEV, "unsupported device");
0650
0651
0652 ret = __kvm_test_create_device(v.vm, gic_dev_type);
0653 if (ret)
0654 return ret;
0655 v.gic_fd = kvm_create_device(v.vm, gic_dev_type);
0656
0657 ret = __kvm_create_device(v.vm, gic_dev_type);
0658 TEST_ASSERT(ret < 0 && errno == EEXIST, "create GIC device twice");
0659
0660
0661 other = VGIC_DEV_IS_V2(gic_dev_type) ? KVM_DEV_TYPE_ARM_VGIC_V3
0662 : KVM_DEV_TYPE_ARM_VGIC_V2;
0663
0664 if (!__kvm_test_create_device(v.vm, other)) {
0665 ret = __kvm_test_create_device(v.vm, other);
0666 TEST_ASSERT(ret && (errno == EINVAL || errno == EEXIST),
0667 "create GIC device while other version exists");
0668 }
0669
0670 vm_gic_destroy(&v);
0671
0672 return 0;
0673 }
0674
0675 void run_tests(uint32_t gic_dev_type)
0676 {
0677 test_vcpus_then_vgic(gic_dev_type);
0678 test_vgic_then_vcpus(gic_dev_type);
0679
0680 if (VGIC_DEV_IS_V3(gic_dev_type)) {
0681 test_v3_new_redist_regions();
0682 test_v3_typer_accesses();
0683 test_v3_last_bit_redist_regions();
0684 test_v3_last_bit_single_rdist();
0685 test_v3_redist_ipa_range_check_at_vcpu_run();
0686 test_v3_its_region();
0687 }
0688 }
0689
0690 int main(int ac, char **av)
0691 {
0692 int ret;
0693 int pa_bits;
0694 int cnt_impl = 0;
0695
0696 pa_bits = vm_guest_mode_params[VM_MODE_DEFAULT].pa_bits;
0697 max_phys_size = 1ULL << pa_bits;
0698
0699 ret = test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V3);
0700 if (!ret) {
0701 pr_info("Running GIC_v3 tests.\n");
0702 run_tests(KVM_DEV_TYPE_ARM_VGIC_V3);
0703 cnt_impl++;
0704 }
0705
0706 ret = test_kvm_device(KVM_DEV_TYPE_ARM_VGIC_V2);
0707 if (!ret) {
0708 pr_info("Running GIC_v2 tests.\n");
0709 run_tests(KVM_DEV_TYPE_ARM_VGIC_V2);
0710 cnt_impl++;
0711 }
0712
0713 if (!cnt_impl) {
0714 print_skip("No GICv2 nor GICv3 support");
0715 exit(KSFT_SKIP);
0716 }
0717 return 0;
0718 }