cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vgic_init.c (22769B)


      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/* helper to access a redistributor register */
     36static 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 */
     46static 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 */
     55static 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
     64static 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
     75static void vm_gic_destroy(struct vm_gic *v)
     76{
     77	close(v->gic_fd);
     78	kvm_vm_free(v->vm);
     79}
     80
     81struct vgic_region_attr {
     82	uint64_t attr;
     83	uint64_t size;
     84	uint64_t alignment;
     85};
     86
     87struct vgic_region_attr gic_v3_dist_region = {
     88	.attr = KVM_VGIC_V3_ADDR_TYPE_DIST,
     89	.size = 0x10000,
     90	.alignment = 0x10000,
     91};
     92
     93struct 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
     99struct vgic_region_attr gic_v2_dist_region = {
    100	.attr = KVM_VGIC_V2_ADDR_TYPE_DIST,
    101	.size = 0x1000,
    102	.alignment = 0x1000,
    103};
    104
    105struct 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 */
    119static 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 */
    203static 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 */
    314static 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 */
    334static 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
    349static 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
    402static 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 */
    481static 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 */
    530static 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. */
    568static 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
    600static 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 */
    644int 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
    682void 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
    697int 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}