162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2015, 2016 ARM Ltd.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/uaccess.h>
762306a36Sopenharmony_ci#include <linux/interrupt.h>
862306a36Sopenharmony_ci#include <linux/cpu.h>
962306a36Sopenharmony_ci#include <linux/kvm_host.h>
1062306a36Sopenharmony_ci#include <kvm/arm_vgic.h>
1162306a36Sopenharmony_ci#include <asm/kvm_emulate.h>
1262306a36Sopenharmony_ci#include <asm/kvm_mmu.h>
1362306a36Sopenharmony_ci#include "vgic.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci * Initialization rules: there are multiple stages to the vgic
1762306a36Sopenharmony_ci * initialization, both for the distributor and the CPU interfaces.  The basic
1862306a36Sopenharmony_ci * idea is that even though the VGIC is not functional or not requested from
1962306a36Sopenharmony_ci * user space, the critical path of the run loop can still call VGIC functions
2062306a36Sopenharmony_ci * that just won't do anything, without them having to check additional
2162306a36Sopenharmony_ci * initialization flags to ensure they don't look at uninitialized data
2262306a36Sopenharmony_ci * structures.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Distributor:
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * - kvm_vgic_early_init(): initialization of static data that doesn't
2762306a36Sopenharmony_ci *   depend on any sizing information or emulation type. No allocation
2862306a36Sopenharmony_ci *   is allowed there.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * - vgic_init(): allocation and initialization of the generic data
3162306a36Sopenharmony_ci *   structures that depend on sizing information (number of CPUs,
3262306a36Sopenharmony_ci *   number of interrupts). Also initializes the vcpu specific data
3362306a36Sopenharmony_ci *   structures. Can be executed lazily for GICv2.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * CPU Interface:
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * - kvm_vgic_vcpu_init(): initialization of static data that
3862306a36Sopenharmony_ci *   doesn't depend on any sizing information or emulation type. No
3962306a36Sopenharmony_ci *   allocation is allowed there.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* EARLY INIT */
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/**
4562306a36Sopenharmony_ci * kvm_vgic_early_init() - Initialize static VGIC VCPU data structures
4662306a36Sopenharmony_ci * @kvm: The VM whose VGIC districutor should be initialized
4762306a36Sopenharmony_ci *
4862306a36Sopenharmony_ci * Only do initialization of static structures that don't require any
4962306a36Sopenharmony_ci * allocation or sizing information from userspace.  vgic_init() called
5062306a36Sopenharmony_ci * kvm_vgic_dist_init() which takes care of the rest.
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_civoid kvm_vgic_early_init(struct kvm *kvm)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	struct vgic_dist *dist = &kvm->arch.vgic;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	INIT_LIST_HEAD(&dist->lpi_list_head);
5762306a36Sopenharmony_ci	INIT_LIST_HEAD(&dist->lpi_translation_cache);
5862306a36Sopenharmony_ci	raw_spin_lock_init(&dist->lpi_list_lock);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/* CREATION */
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/**
6462306a36Sopenharmony_ci * kvm_vgic_create: triggered by the instantiation of the VGIC device by
6562306a36Sopenharmony_ci * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
6662306a36Sopenharmony_ci * or through the generic KVM_CREATE_DEVICE API ioctl.
6762306a36Sopenharmony_ci * irqchip_in_kernel() tells you if this function succeeded or not.
6862306a36Sopenharmony_ci * @kvm: kvm struct pointer
6962306a36Sopenharmony_ci * @type: KVM_DEV_TYPE_ARM_VGIC_V[23]
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_ciint kvm_vgic_create(struct kvm *kvm, u32 type)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct kvm_vcpu *vcpu;
7462306a36Sopenharmony_ci	unsigned long i;
7562306a36Sopenharmony_ci	int ret;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/*
7862306a36Sopenharmony_ci	 * This function is also called by the KVM_CREATE_IRQCHIP handler,
7962306a36Sopenharmony_ci	 * which had no chance yet to check the availability of the GICv2
8062306a36Sopenharmony_ci	 * emulation. So check this here again. KVM_CREATE_DEVICE does
8162306a36Sopenharmony_ci	 * the proper checks already.
8262306a36Sopenharmony_ci	 */
8362306a36Sopenharmony_ci	if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
8462306a36Sopenharmony_ci		!kvm_vgic_global_state.can_emulate_gicv2)
8562306a36Sopenharmony_ci		return -ENODEV;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/* Must be held to avoid race with vCPU creation */
8862306a36Sopenharmony_ci	lockdep_assert_held(&kvm->lock);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	ret = -EBUSY;
9162306a36Sopenharmony_ci	if (!lock_all_vcpus(kvm))
9262306a36Sopenharmony_ci		return ret;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	mutex_lock(&kvm->arch.config_lock);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (irqchip_in_kernel(kvm)) {
9762306a36Sopenharmony_ci		ret = -EEXIST;
9862306a36Sopenharmony_ci		goto out_unlock;
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
10262306a36Sopenharmony_ci		if (vcpu_has_run_once(vcpu))
10362306a36Sopenharmony_ci			goto out_unlock;
10462306a36Sopenharmony_ci	}
10562306a36Sopenharmony_ci	ret = 0;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
10862306a36Sopenharmony_ci		kvm->max_vcpus = VGIC_V2_MAX_CPUS;
10962306a36Sopenharmony_ci	else
11062306a36Sopenharmony_ci		kvm->max_vcpus = VGIC_V3_MAX_CPUS;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	if (atomic_read(&kvm->online_vcpus) > kvm->max_vcpus) {
11362306a36Sopenharmony_ci		ret = -E2BIG;
11462306a36Sopenharmony_ci		goto out_unlock;
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	kvm->arch.vgic.in_kernel = true;
11862306a36Sopenharmony_ci	kvm->arch.vgic.vgic_model = type;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
12362306a36Sopenharmony_ci		kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
12462306a36Sopenharmony_ci	else
12562306a36Sopenharmony_ci		INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciout_unlock:
12862306a36Sopenharmony_ci	mutex_unlock(&kvm->arch.config_lock);
12962306a36Sopenharmony_ci	unlock_all_vcpus(kvm);
13062306a36Sopenharmony_ci	return ret;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/* INIT/DESTROY */
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/**
13662306a36Sopenharmony_ci * kvm_vgic_dist_init: initialize the dist data structures
13762306a36Sopenharmony_ci * @kvm: kvm struct pointer
13862306a36Sopenharmony_ci * @nr_spis: number of spis, frozen by caller
13962306a36Sopenharmony_ci */
14062306a36Sopenharmony_cistatic int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	struct vgic_dist *dist = &kvm->arch.vgic;
14362306a36Sopenharmony_ci	struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
14462306a36Sopenharmony_ci	int i;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL_ACCOUNT);
14762306a36Sopenharmony_ci	if (!dist->spis)
14862306a36Sopenharmony_ci		return  -ENOMEM;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/*
15162306a36Sopenharmony_ci	 * In the following code we do not take the irq struct lock since
15262306a36Sopenharmony_ci	 * no other action on irq structs can happen while the VGIC is
15362306a36Sopenharmony_ci	 * not initialized yet:
15462306a36Sopenharmony_ci	 * If someone wants to inject an interrupt or does a MMIO access, we
15562306a36Sopenharmony_ci	 * require prior initialization in case of a virtual GICv3 or trigger
15662306a36Sopenharmony_ci	 * initialization when using a virtual GICv2.
15762306a36Sopenharmony_ci	 */
15862306a36Sopenharmony_ci	for (i = 0; i < nr_spis; i++) {
15962306a36Sopenharmony_ci		struct vgic_irq *irq = &dist->spis[i];
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci		irq->intid = i + VGIC_NR_PRIVATE_IRQS;
16262306a36Sopenharmony_ci		INIT_LIST_HEAD(&irq->ap_list);
16362306a36Sopenharmony_ci		raw_spin_lock_init(&irq->irq_lock);
16462306a36Sopenharmony_ci		irq->vcpu = NULL;
16562306a36Sopenharmony_ci		irq->target_vcpu = vcpu0;
16662306a36Sopenharmony_ci		kref_init(&irq->refcount);
16762306a36Sopenharmony_ci		switch (dist->vgic_model) {
16862306a36Sopenharmony_ci		case KVM_DEV_TYPE_ARM_VGIC_V2:
16962306a36Sopenharmony_ci			irq->targets = 0;
17062306a36Sopenharmony_ci			irq->group = 0;
17162306a36Sopenharmony_ci			break;
17262306a36Sopenharmony_ci		case KVM_DEV_TYPE_ARM_VGIC_V3:
17362306a36Sopenharmony_ci			irq->mpidr = 0;
17462306a36Sopenharmony_ci			irq->group = 1;
17562306a36Sopenharmony_ci			break;
17662306a36Sopenharmony_ci		default:
17762306a36Sopenharmony_ci			kfree(dist->spis);
17862306a36Sopenharmony_ci			dist->spis = NULL;
17962306a36Sopenharmony_ci			return -EINVAL;
18062306a36Sopenharmony_ci		}
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci	return 0;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/**
18662306a36Sopenharmony_ci * kvm_vgic_vcpu_init() - Initialize static VGIC VCPU data
18762306a36Sopenharmony_ci * structures and register VCPU-specific KVM iodevs
18862306a36Sopenharmony_ci *
18962306a36Sopenharmony_ci * @vcpu: pointer to the VCPU being created and initialized
19062306a36Sopenharmony_ci *
19162306a36Sopenharmony_ci * Only do initialization, but do not actually enable the
19262306a36Sopenharmony_ci * VGIC CPU interface
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_ciint kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
19762306a36Sopenharmony_ci	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
19862306a36Sopenharmony_ci	int ret = 0;
19962306a36Sopenharmony_ci	int i;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
20462306a36Sopenharmony_ci	raw_spin_lock_init(&vgic_cpu->ap_list_lock);
20562306a36Sopenharmony_ci	atomic_set(&vgic_cpu->vgic_v3.its_vpe.vlpi_count, 0);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	/*
20862306a36Sopenharmony_ci	 * Enable and configure all SGIs to be edge-triggered and
20962306a36Sopenharmony_ci	 * configure all PPIs as level-triggered.
21062306a36Sopenharmony_ci	 */
21162306a36Sopenharmony_ci	for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
21262306a36Sopenharmony_ci		struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci		INIT_LIST_HEAD(&irq->ap_list);
21562306a36Sopenharmony_ci		raw_spin_lock_init(&irq->irq_lock);
21662306a36Sopenharmony_ci		irq->intid = i;
21762306a36Sopenharmony_ci		irq->vcpu = NULL;
21862306a36Sopenharmony_ci		irq->target_vcpu = vcpu;
21962306a36Sopenharmony_ci		kref_init(&irq->refcount);
22062306a36Sopenharmony_ci		if (vgic_irq_is_sgi(i)) {
22162306a36Sopenharmony_ci			/* SGIs */
22262306a36Sopenharmony_ci			irq->enabled = 1;
22362306a36Sopenharmony_ci			irq->config = VGIC_CONFIG_EDGE;
22462306a36Sopenharmony_ci		} else {
22562306a36Sopenharmony_ci			/* PPIs */
22662306a36Sopenharmony_ci			irq->config = VGIC_CONFIG_LEVEL;
22762306a36Sopenharmony_ci		}
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	if (!irqchip_in_kernel(vcpu->kvm))
23162306a36Sopenharmony_ci		return 0;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	/*
23462306a36Sopenharmony_ci	 * If we are creating a VCPU with a GICv3 we must also register the
23562306a36Sopenharmony_ci	 * KVM io device for the redistributor that belongs to this VCPU.
23662306a36Sopenharmony_ci	 */
23762306a36Sopenharmony_ci	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
23862306a36Sopenharmony_ci		mutex_lock(&vcpu->kvm->slots_lock);
23962306a36Sopenharmony_ci		ret = vgic_register_redist_iodev(vcpu);
24062306a36Sopenharmony_ci		mutex_unlock(&vcpu->kvm->slots_lock);
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci	return ret;
24362306a36Sopenharmony_ci}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic void kvm_vgic_vcpu_enable(struct kvm_vcpu *vcpu)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	if (kvm_vgic_global_state.type == VGIC_V2)
24862306a36Sopenharmony_ci		vgic_v2_enable(vcpu);
24962306a36Sopenharmony_ci	else
25062306a36Sopenharmony_ci		vgic_v3_enable(vcpu);
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci/*
25462306a36Sopenharmony_ci * vgic_init: allocates and initializes dist and vcpu data structures
25562306a36Sopenharmony_ci * depending on two dimensioning parameters:
25662306a36Sopenharmony_ci * - the number of spis
25762306a36Sopenharmony_ci * - the number of vcpus
25862306a36Sopenharmony_ci * The function is generally called when nr_spis has been explicitly set
25962306a36Sopenharmony_ci * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
26062306a36Sopenharmony_ci * vgic_initialized() returns true when this function has succeeded.
26162306a36Sopenharmony_ci */
26262306a36Sopenharmony_ciint vgic_init(struct kvm *kvm)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	struct vgic_dist *dist = &kvm->arch.vgic;
26562306a36Sopenharmony_ci	struct kvm_vcpu *vcpu;
26662306a36Sopenharmony_ci	int ret = 0, i;
26762306a36Sopenharmony_ci	unsigned long idx;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	lockdep_assert_held(&kvm->arch.config_lock);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (vgic_initialized(kvm))
27262306a36Sopenharmony_ci		return 0;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	/* Are we also in the middle of creating a VCPU? */
27562306a36Sopenharmony_ci	if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus))
27662306a36Sopenharmony_ci		return -EBUSY;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	/* freeze the number of spis */
27962306a36Sopenharmony_ci	if (!dist->nr_spis)
28062306a36Sopenharmony_ci		dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	ret = kvm_vgic_dist_init(kvm, dist->nr_spis);
28362306a36Sopenharmony_ci	if (ret)
28462306a36Sopenharmony_ci		goto out;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	/* Initialize groups on CPUs created before the VGIC type was known */
28762306a36Sopenharmony_ci	kvm_for_each_vcpu(idx, vcpu, kvm) {
28862306a36Sopenharmony_ci		struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci		for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
29162306a36Sopenharmony_ci			struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
29262306a36Sopenharmony_ci			switch (dist->vgic_model) {
29362306a36Sopenharmony_ci			case KVM_DEV_TYPE_ARM_VGIC_V3:
29462306a36Sopenharmony_ci				irq->group = 1;
29562306a36Sopenharmony_ci				irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
29662306a36Sopenharmony_ci				break;
29762306a36Sopenharmony_ci			case KVM_DEV_TYPE_ARM_VGIC_V2:
29862306a36Sopenharmony_ci				irq->group = 0;
29962306a36Sopenharmony_ci				irq->targets = 1U << idx;
30062306a36Sopenharmony_ci				break;
30162306a36Sopenharmony_ci			default:
30262306a36Sopenharmony_ci				ret = -EINVAL;
30362306a36Sopenharmony_ci				goto out;
30462306a36Sopenharmony_ci			}
30562306a36Sopenharmony_ci		}
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	if (vgic_has_its(kvm))
30962306a36Sopenharmony_ci		vgic_lpi_translation_cache_init(kvm);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/*
31262306a36Sopenharmony_ci	 * If we have GICv4.1 enabled, unconditionnaly request enable the
31362306a36Sopenharmony_ci	 * v4 support so that we get HW-accelerated vSGIs. Otherwise, only
31462306a36Sopenharmony_ci	 * enable it if we present a virtual ITS to the guest.
31562306a36Sopenharmony_ci	 */
31662306a36Sopenharmony_ci	if (vgic_supports_direct_msis(kvm)) {
31762306a36Sopenharmony_ci		ret = vgic_v4_init(kvm);
31862306a36Sopenharmony_ci		if (ret)
31962306a36Sopenharmony_ci			goto out;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	kvm_for_each_vcpu(idx, vcpu, kvm)
32362306a36Sopenharmony_ci		kvm_vgic_vcpu_enable(vcpu);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	ret = kvm_vgic_setup_default_irq_routing(kvm);
32662306a36Sopenharmony_ci	if (ret)
32762306a36Sopenharmony_ci		goto out;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	vgic_debug_init(kvm);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/*
33262306a36Sopenharmony_ci	 * If userspace didn't set the GIC implementation revision,
33362306a36Sopenharmony_ci	 * default to the latest and greatest. You know want it.
33462306a36Sopenharmony_ci	 */
33562306a36Sopenharmony_ci	if (!dist->implementation_rev)
33662306a36Sopenharmony_ci		dist->implementation_rev = KVM_VGIC_IMP_REV_LATEST;
33762306a36Sopenharmony_ci	dist->initialized = true;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ciout:
34062306a36Sopenharmony_ci	return ret;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic void kvm_vgic_dist_destroy(struct kvm *kvm)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct vgic_dist *dist = &kvm->arch.vgic;
34662306a36Sopenharmony_ci	struct vgic_redist_region *rdreg, *next;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	dist->ready = false;
34962306a36Sopenharmony_ci	dist->initialized = false;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	kfree(dist->spis);
35262306a36Sopenharmony_ci	dist->spis = NULL;
35362306a36Sopenharmony_ci	dist->nr_spis = 0;
35462306a36Sopenharmony_ci	dist->vgic_dist_base = VGIC_ADDR_UNDEF;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
35762306a36Sopenharmony_ci		list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list)
35862306a36Sopenharmony_ci			vgic_v3_free_redist_region(rdreg);
35962306a36Sopenharmony_ci		INIT_LIST_HEAD(&dist->rd_regions);
36062306a36Sopenharmony_ci	} else {
36162306a36Sopenharmony_ci		dist->vgic_cpu_base = VGIC_ADDR_UNDEF;
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (vgic_has_its(kvm))
36562306a36Sopenharmony_ci		vgic_lpi_translation_cache_destroy(kvm);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	if (vgic_supports_direct_msis(kvm))
36862306a36Sopenharmony_ci		vgic_v4_teardown(kvm);
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistatic void __kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	/*
37662306a36Sopenharmony_ci	 * Retire all pending LPIs on this vcpu anyway as we're
37762306a36Sopenharmony_ci	 * going to destroy it.
37862306a36Sopenharmony_ci	 */
37962306a36Sopenharmony_ci	vgic_flush_pending_lpis(vcpu);
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
38262306a36Sopenharmony_ci	if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
38362306a36Sopenharmony_ci		vgic_unregister_redist_iodev(vcpu);
38462306a36Sopenharmony_ci		vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_civoid kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	struct kvm *kvm = vcpu->kvm;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	mutex_lock(&kvm->slots_lock);
39362306a36Sopenharmony_ci	__kvm_vgic_vcpu_destroy(vcpu);
39462306a36Sopenharmony_ci	mutex_unlock(&kvm->slots_lock);
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_civoid kvm_vgic_destroy(struct kvm *kvm)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	struct kvm_vcpu *vcpu;
40062306a36Sopenharmony_ci	unsigned long i;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	mutex_lock(&kvm->slots_lock);
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	vgic_debug_destroy(kvm);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm)
40762306a36Sopenharmony_ci		__kvm_vgic_vcpu_destroy(vcpu);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	mutex_lock(&kvm->arch.config_lock);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	kvm_vgic_dist_destroy(kvm);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	mutex_unlock(&kvm->arch.config_lock);
41462306a36Sopenharmony_ci	mutex_unlock(&kvm->slots_lock);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci/**
41862306a36Sopenharmony_ci * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
41962306a36Sopenharmony_ci * is a GICv2. A GICv3 must be explicitly initialized by userspace using the
42062306a36Sopenharmony_ci * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group.
42162306a36Sopenharmony_ci * @kvm: kvm struct pointer
42262306a36Sopenharmony_ci */
42362306a36Sopenharmony_ciint vgic_lazy_init(struct kvm *kvm)
42462306a36Sopenharmony_ci{
42562306a36Sopenharmony_ci	int ret = 0;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	if (unlikely(!vgic_initialized(kvm))) {
42862306a36Sopenharmony_ci		/*
42962306a36Sopenharmony_ci		 * We only provide the automatic initialization of the VGIC
43062306a36Sopenharmony_ci		 * for the legacy case of a GICv2. Any other type must
43162306a36Sopenharmony_ci		 * be explicitly initialized once setup with the respective
43262306a36Sopenharmony_ci		 * KVM device call.
43362306a36Sopenharmony_ci		 */
43462306a36Sopenharmony_ci		if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
43562306a36Sopenharmony_ci			return -EBUSY;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci		mutex_lock(&kvm->arch.config_lock);
43862306a36Sopenharmony_ci		ret = vgic_init(kvm);
43962306a36Sopenharmony_ci		mutex_unlock(&kvm->arch.config_lock);
44062306a36Sopenharmony_ci	}
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	return ret;
44362306a36Sopenharmony_ci}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci/* RESOURCE MAPPING */
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci/**
44862306a36Sopenharmony_ci * Map the MMIO regions depending on the VGIC model exposed to the guest
44962306a36Sopenharmony_ci * called on the first VCPU run.
45062306a36Sopenharmony_ci * Also map the virtual CPU interface into the VM.
45162306a36Sopenharmony_ci * v2 calls vgic_init() if not already done.
45262306a36Sopenharmony_ci * v3 and derivatives return an error if the VGIC is not initialized.
45362306a36Sopenharmony_ci * vgic_ready() returns true if this function has succeeded.
45462306a36Sopenharmony_ci * @kvm: kvm struct pointer
45562306a36Sopenharmony_ci */
45662306a36Sopenharmony_ciint kvm_vgic_map_resources(struct kvm *kvm)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	struct vgic_dist *dist = &kvm->arch.vgic;
45962306a36Sopenharmony_ci	enum vgic_type type;
46062306a36Sopenharmony_ci	gpa_t dist_base;
46162306a36Sopenharmony_ci	int ret = 0;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	if (likely(vgic_ready(kvm)))
46462306a36Sopenharmony_ci		return 0;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	mutex_lock(&kvm->slots_lock);
46762306a36Sopenharmony_ci	mutex_lock(&kvm->arch.config_lock);
46862306a36Sopenharmony_ci	if (vgic_ready(kvm))
46962306a36Sopenharmony_ci		goto out;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	if (!irqchip_in_kernel(kvm))
47262306a36Sopenharmony_ci		goto out;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
47562306a36Sopenharmony_ci		ret = vgic_v2_map_resources(kvm);
47662306a36Sopenharmony_ci		type = VGIC_V2;
47762306a36Sopenharmony_ci	} else {
47862306a36Sopenharmony_ci		ret = vgic_v3_map_resources(kvm);
47962306a36Sopenharmony_ci		type = VGIC_V3;
48062306a36Sopenharmony_ci	}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	if (ret)
48362306a36Sopenharmony_ci		goto out;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	dist->ready = true;
48662306a36Sopenharmony_ci	dist_base = dist->vgic_dist_base;
48762306a36Sopenharmony_ci	mutex_unlock(&kvm->arch.config_lock);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	ret = vgic_register_dist_iodev(kvm, dist_base, type);
49062306a36Sopenharmony_ci	if (ret)
49162306a36Sopenharmony_ci		kvm_err("Unable to register VGIC dist MMIO regions\n");
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	goto out_slots;
49462306a36Sopenharmony_ciout:
49562306a36Sopenharmony_ci	mutex_unlock(&kvm->arch.config_lock);
49662306a36Sopenharmony_ciout_slots:
49762306a36Sopenharmony_ci	mutex_unlock(&kvm->slots_lock);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (ret)
50062306a36Sopenharmony_ci		kvm_vgic_destroy(kvm);
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	return ret;
50362306a36Sopenharmony_ci}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci/* GENERIC PROBE */
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_civoid kvm_vgic_cpu_up(void)
50862306a36Sopenharmony_ci{
50962306a36Sopenharmony_ci	enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
51062306a36Sopenharmony_ci}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_civoid kvm_vgic_cpu_down(void)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	disable_percpu_irq(kvm_vgic_global_state.maint_irq);
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic irqreturn_t vgic_maintenance_handler(int irq, void *data)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	/*
52162306a36Sopenharmony_ci	 * We cannot rely on the vgic maintenance interrupt to be
52262306a36Sopenharmony_ci	 * delivered synchronously. This means we can only use it to
52362306a36Sopenharmony_ci	 * exit the VM, and we perform the handling of EOIed
52462306a36Sopenharmony_ci	 * interrupts on the exit path (see vgic_fold_lr_state).
52562306a36Sopenharmony_ci	 */
52662306a36Sopenharmony_ci	return IRQ_HANDLED;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic struct gic_kvm_info *gic_kvm_info;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_civoid __init vgic_set_kvm_info(const struct gic_kvm_info *info)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	BUG_ON(gic_kvm_info != NULL);
53462306a36Sopenharmony_ci	gic_kvm_info = kmalloc(sizeof(*info), GFP_KERNEL);
53562306a36Sopenharmony_ci	if (gic_kvm_info)
53662306a36Sopenharmony_ci		*gic_kvm_info = *info;
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci/**
54062306a36Sopenharmony_ci * kvm_vgic_init_cpu_hardware - initialize the GIC VE hardware
54162306a36Sopenharmony_ci *
54262306a36Sopenharmony_ci * For a specific CPU, initialize the GIC VE hardware.
54362306a36Sopenharmony_ci */
54462306a36Sopenharmony_civoid kvm_vgic_init_cpu_hardware(void)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	BUG_ON(preemptible());
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	/*
54962306a36Sopenharmony_ci	 * We want to make sure the list registers start out clear so that we
55062306a36Sopenharmony_ci	 * only have the program the used registers.
55162306a36Sopenharmony_ci	 */
55262306a36Sopenharmony_ci	if (kvm_vgic_global_state.type == VGIC_V2)
55362306a36Sopenharmony_ci		vgic_v2_init_lrs();
55462306a36Sopenharmony_ci	else
55562306a36Sopenharmony_ci		kvm_call_hyp(__vgic_v3_init_lrs);
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci/**
55962306a36Sopenharmony_ci * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable
56062306a36Sopenharmony_ci * according to the host GIC model. Accordingly calls either
56162306a36Sopenharmony_ci * vgic_v2/v3_probe which registers the KVM_DEVICE that can be
56262306a36Sopenharmony_ci * instantiated by a guest later on .
56362306a36Sopenharmony_ci */
56462306a36Sopenharmony_ciint kvm_vgic_hyp_init(void)
56562306a36Sopenharmony_ci{
56662306a36Sopenharmony_ci	bool has_mask;
56762306a36Sopenharmony_ci	int ret;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if (!gic_kvm_info)
57062306a36Sopenharmony_ci		return -ENODEV;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	has_mask = !gic_kvm_info->no_maint_irq_mask;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	if (has_mask && !gic_kvm_info->maint_irq) {
57562306a36Sopenharmony_ci		kvm_err("No vgic maintenance irq\n");
57662306a36Sopenharmony_ci		return -ENXIO;
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	/*
58062306a36Sopenharmony_ci	 * If we get one of these oddball non-GICs, taint the kernel,
58162306a36Sopenharmony_ci	 * as we have no idea of how they *really* behave.
58262306a36Sopenharmony_ci	 */
58362306a36Sopenharmony_ci	if (gic_kvm_info->no_hw_deactivation) {
58462306a36Sopenharmony_ci		kvm_info("Non-architectural vgic, tainting kernel\n");
58562306a36Sopenharmony_ci		add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
58662306a36Sopenharmony_ci		kvm_vgic_global_state.no_hw_deactivation = true;
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	switch (gic_kvm_info->type) {
59062306a36Sopenharmony_ci	case GIC_V2:
59162306a36Sopenharmony_ci		ret = vgic_v2_probe(gic_kvm_info);
59262306a36Sopenharmony_ci		break;
59362306a36Sopenharmony_ci	case GIC_V3:
59462306a36Sopenharmony_ci		ret = vgic_v3_probe(gic_kvm_info);
59562306a36Sopenharmony_ci		if (!ret) {
59662306a36Sopenharmony_ci			static_branch_enable(&kvm_vgic_global_state.gicv3_cpuif);
59762306a36Sopenharmony_ci			kvm_info("GIC system register CPU interface enabled\n");
59862306a36Sopenharmony_ci		}
59962306a36Sopenharmony_ci		break;
60062306a36Sopenharmony_ci	default:
60162306a36Sopenharmony_ci		ret = -ENODEV;
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	kfree(gic_kvm_info);
60762306a36Sopenharmony_ci	gic_kvm_info = NULL;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	if (ret)
61062306a36Sopenharmony_ci		return ret;
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	if (!has_mask && !kvm_vgic_global_state.maint_irq)
61362306a36Sopenharmony_ci		return 0;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
61662306a36Sopenharmony_ci				 vgic_maintenance_handler,
61762306a36Sopenharmony_ci				 "vgic", kvm_get_running_vcpus());
61862306a36Sopenharmony_ci	if (ret) {
61962306a36Sopenharmony_ci		kvm_err("Cannot register interrupt %d\n",
62062306a36Sopenharmony_ci			kvm_vgic_global_state.maint_irq);
62162306a36Sopenharmony_ci		return ret;
62262306a36Sopenharmony_ci	}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
62562306a36Sopenharmony_ci	return 0;
62662306a36Sopenharmony_ci}
627