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