Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: selftests: aarch64/vgic-v3 init sequence tests

The tests exercise the VGIC_V3 device creation including the
associated KVM_DEV_ARM_VGIC_GRP_ADDR group attributes:

- KVM_VGIC_V3_ADDR_TYPE_DIST/REDIST
- KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION

Some other tests dedicate to KVM_DEV_ARM_VGIC_GRP_REDIST_REGS group
and especially the GICR_TYPER read. The goal was to test the case
recently fixed by commit 23bde34771f1
("KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace").

The API under test can be found at
Documentation/virt/kvm/devices/arm-vgic-v3.rst

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210405163941.510258-10-eric.auger@redhat.com

authored by

Eric Auger and committed by
Marc Zyngier
dc0e058e 28e9d4bc

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