18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015, 2016 ARM Ltd. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 78c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 88c2ecf20Sopenharmony_ci#include <linux/cpu.h> 98c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 108c2ecf20Sopenharmony_ci#include <kvm/arm_vgic.h> 118c2ecf20Sopenharmony_ci#include <asm/kvm_emulate.h> 128c2ecf20Sopenharmony_ci#include <asm/kvm_mmu.h> 138c2ecf20Sopenharmony_ci#include "vgic.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* 168c2ecf20Sopenharmony_ci * Initialization rules: there are multiple stages to the vgic 178c2ecf20Sopenharmony_ci * initialization, both for the distributor and the CPU interfaces. The basic 188c2ecf20Sopenharmony_ci * idea is that even though the VGIC is not functional or not requested from 198c2ecf20Sopenharmony_ci * user space, the critical path of the run loop can still call VGIC functions 208c2ecf20Sopenharmony_ci * that just won't do anything, without them having to check additional 218c2ecf20Sopenharmony_ci * initialization flags to ensure they don't look at uninitialized data 228c2ecf20Sopenharmony_ci * structures. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Distributor: 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * - kvm_vgic_early_init(): initialization of static data that doesn't 278c2ecf20Sopenharmony_ci * depend on any sizing information or emulation type. No allocation 288c2ecf20Sopenharmony_ci * is allowed there. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * - vgic_init(): allocation and initialization of the generic data 318c2ecf20Sopenharmony_ci * structures that depend on sizing information (number of CPUs, 328c2ecf20Sopenharmony_ci * number of interrupts). Also initializes the vcpu specific data 338c2ecf20Sopenharmony_ci * structures. Can be executed lazily for GICv2. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * CPU Interface: 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * - kvm_vgic_vcpu_init(): initialization of static data that 388c2ecf20Sopenharmony_ci * doesn't depend on any sizing information or emulation type. No 398c2ecf20Sopenharmony_ci * allocation is allowed there. 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* EARLY INIT */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/** 458c2ecf20Sopenharmony_ci * kvm_vgic_early_init() - Initialize static VGIC VCPU data structures 468c2ecf20Sopenharmony_ci * @kvm: The VM whose VGIC districutor should be initialized 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci * Only do initialization of static structures that don't require any 498c2ecf20Sopenharmony_ci * allocation or sizing information from userspace. vgic_init() called 508c2ecf20Sopenharmony_ci * kvm_vgic_dist_init() which takes care of the rest. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_civoid kvm_vgic_early_init(struct kvm *kvm) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct vgic_dist *dist = &kvm->arch.vgic; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dist->lpi_list_head); 578c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dist->lpi_translation_cache); 588c2ecf20Sopenharmony_ci raw_spin_lock_init(&dist->lpi_list_lock); 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* CREATION */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/** 648c2ecf20Sopenharmony_ci * kvm_vgic_create: triggered by the instantiation of the VGIC device by 658c2ecf20Sopenharmony_ci * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only) 668c2ecf20Sopenharmony_ci * or through the generic KVM_CREATE_DEVICE API ioctl. 678c2ecf20Sopenharmony_ci * irqchip_in_kernel() tells you if this function succeeded or not. 688c2ecf20Sopenharmony_ci * @kvm: kvm struct pointer 698c2ecf20Sopenharmony_ci * @type: KVM_DEV_TYPE_ARM_VGIC_V[23] 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ciint kvm_vgic_create(struct kvm *kvm, u32 type) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci int i, ret; 748c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (irqchip_in_kernel(kvm)) 778c2ecf20Sopenharmony_ci return -EEXIST; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* 808c2ecf20Sopenharmony_ci * This function is also called by the KVM_CREATE_IRQCHIP handler, 818c2ecf20Sopenharmony_ci * which had no chance yet to check the availability of the GICv2 828c2ecf20Sopenharmony_ci * emulation. So check this here again. KVM_CREATE_DEVICE does 838c2ecf20Sopenharmony_ci * the proper checks already. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci if (type == KVM_DEV_TYPE_ARM_VGIC_V2 && 868c2ecf20Sopenharmony_ci !kvm_vgic_global_state.can_emulate_gicv2) 878c2ecf20Sopenharmony_ci return -ENODEV; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci ret = -EBUSY; 908c2ecf20Sopenharmony_ci if (!lock_all_vcpus(kvm)) 918c2ecf20Sopenharmony_ci return ret; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) { 948c2ecf20Sopenharmony_ci if (vcpu->arch.has_run_once) 958c2ecf20Sopenharmony_ci goto out_unlock; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci ret = 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (type == KVM_DEV_TYPE_ARM_VGIC_V2) 1008c2ecf20Sopenharmony_ci kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS; 1018c2ecf20Sopenharmony_ci else 1028c2ecf20Sopenharmony_ci kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) { 1058c2ecf20Sopenharmony_ci ret = -E2BIG; 1068c2ecf20Sopenharmony_ci goto out_unlock; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci kvm->arch.vgic.in_kernel = true; 1108c2ecf20Sopenharmony_ci kvm->arch.vgic.vgic_model = type; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (type == KVM_DEV_TYPE_ARM_VGIC_V2) 1158c2ecf20Sopenharmony_ci kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; 1168c2ecf20Sopenharmony_ci else 1178c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciout_unlock: 1208c2ecf20Sopenharmony_ci unlock_all_vcpus(kvm); 1218c2ecf20Sopenharmony_ci return ret; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci/* INIT/DESTROY */ 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/** 1278c2ecf20Sopenharmony_ci * kvm_vgic_dist_init: initialize the dist data structures 1288c2ecf20Sopenharmony_ci * @kvm: kvm struct pointer 1298c2ecf20Sopenharmony_ci * @nr_spis: number of spis, frozen by caller 1308c2ecf20Sopenharmony_ci */ 1318c2ecf20Sopenharmony_cistatic int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct vgic_dist *dist = &kvm->arch.vgic; 1348c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0); 1358c2ecf20Sopenharmony_ci int i; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL); 1388c2ecf20Sopenharmony_ci if (!dist->spis) 1398c2ecf20Sopenharmony_ci return -ENOMEM; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* 1428c2ecf20Sopenharmony_ci * In the following code we do not take the irq struct lock since 1438c2ecf20Sopenharmony_ci * no other action on irq structs can happen while the VGIC is 1448c2ecf20Sopenharmony_ci * not initialized yet: 1458c2ecf20Sopenharmony_ci * If someone wants to inject an interrupt or does a MMIO access, we 1468c2ecf20Sopenharmony_ci * require prior initialization in case of a virtual GICv3 or trigger 1478c2ecf20Sopenharmony_ci * initialization when using a virtual GICv2. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci for (i = 0; i < nr_spis; i++) { 1508c2ecf20Sopenharmony_ci struct vgic_irq *irq = &dist->spis[i]; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci irq->intid = i + VGIC_NR_PRIVATE_IRQS; 1538c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&irq->ap_list); 1548c2ecf20Sopenharmony_ci raw_spin_lock_init(&irq->irq_lock); 1558c2ecf20Sopenharmony_ci irq->vcpu = NULL; 1568c2ecf20Sopenharmony_ci irq->target_vcpu = vcpu0; 1578c2ecf20Sopenharmony_ci kref_init(&irq->refcount); 1588c2ecf20Sopenharmony_ci switch (dist->vgic_model) { 1598c2ecf20Sopenharmony_ci case KVM_DEV_TYPE_ARM_VGIC_V2: 1608c2ecf20Sopenharmony_ci irq->targets = 0; 1618c2ecf20Sopenharmony_ci irq->group = 0; 1628c2ecf20Sopenharmony_ci break; 1638c2ecf20Sopenharmony_ci case KVM_DEV_TYPE_ARM_VGIC_V3: 1648c2ecf20Sopenharmony_ci irq->mpidr = 0; 1658c2ecf20Sopenharmony_ci irq->group = 1; 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci default: 1688c2ecf20Sopenharmony_ci kfree(dist->spis); 1698c2ecf20Sopenharmony_ci dist->spis = NULL; 1708c2ecf20Sopenharmony_ci return -EINVAL; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci return 0; 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci/** 1778c2ecf20Sopenharmony_ci * kvm_vgic_vcpu_init() - Initialize static VGIC VCPU data 1788c2ecf20Sopenharmony_ci * structures and register VCPU-specific KVM iodevs 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * @vcpu: pointer to the VCPU being created and initialized 1818c2ecf20Sopenharmony_ci * 1828c2ecf20Sopenharmony_ci * Only do initialization, but do not actually enable the 1838c2ecf20Sopenharmony_ci * VGIC CPU interface 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ciint kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 1888c2ecf20Sopenharmony_ci struct vgic_dist *dist = &vcpu->kvm->arch.vgic; 1898c2ecf20Sopenharmony_ci int ret = 0; 1908c2ecf20Sopenharmony_ci int i; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vgic_cpu->ap_list_head); 1958c2ecf20Sopenharmony_ci raw_spin_lock_init(&vgic_cpu->ap_list_lock); 1968c2ecf20Sopenharmony_ci atomic_set(&vgic_cpu->vgic_v3.its_vpe.vlpi_count, 0); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* 1998c2ecf20Sopenharmony_ci * Enable and configure all SGIs to be edge-triggered and 2008c2ecf20Sopenharmony_ci * configure all PPIs as level-triggered. 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_ci for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) { 2038c2ecf20Sopenharmony_ci struct vgic_irq *irq = &vgic_cpu->private_irqs[i]; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&irq->ap_list); 2068c2ecf20Sopenharmony_ci raw_spin_lock_init(&irq->irq_lock); 2078c2ecf20Sopenharmony_ci irq->intid = i; 2088c2ecf20Sopenharmony_ci irq->vcpu = NULL; 2098c2ecf20Sopenharmony_ci irq->target_vcpu = vcpu; 2108c2ecf20Sopenharmony_ci kref_init(&irq->refcount); 2118c2ecf20Sopenharmony_ci if (vgic_irq_is_sgi(i)) { 2128c2ecf20Sopenharmony_ci /* SGIs */ 2138c2ecf20Sopenharmony_ci irq->enabled = 1; 2148c2ecf20Sopenharmony_ci irq->config = VGIC_CONFIG_EDGE; 2158c2ecf20Sopenharmony_ci } else { 2168c2ecf20Sopenharmony_ci /* PPIs */ 2178c2ecf20Sopenharmony_ci irq->config = VGIC_CONFIG_LEVEL; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!irqchip_in_kernel(vcpu->kvm)) 2228c2ecf20Sopenharmony_ci return 0; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* 2258c2ecf20Sopenharmony_ci * If we are creating a VCPU with a GICv3 we must also register the 2268c2ecf20Sopenharmony_ci * KVM io device for the redistributor that belongs to this VCPU. 2278c2ecf20Sopenharmony_ci */ 2288c2ecf20Sopenharmony_ci if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { 2298c2ecf20Sopenharmony_ci mutex_lock(&vcpu->kvm->lock); 2308c2ecf20Sopenharmony_ci ret = vgic_register_redist_iodev(vcpu); 2318c2ecf20Sopenharmony_ci mutex_unlock(&vcpu->kvm->lock); 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci return ret; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic void kvm_vgic_vcpu_enable(struct kvm_vcpu *vcpu) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci if (kvm_vgic_global_state.type == VGIC_V2) 2398c2ecf20Sopenharmony_ci vgic_v2_enable(vcpu); 2408c2ecf20Sopenharmony_ci else 2418c2ecf20Sopenharmony_ci vgic_v3_enable(vcpu); 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci/* 2458c2ecf20Sopenharmony_ci * vgic_init: allocates and initializes dist and vcpu data structures 2468c2ecf20Sopenharmony_ci * depending on two dimensioning parameters: 2478c2ecf20Sopenharmony_ci * - the number of spis 2488c2ecf20Sopenharmony_ci * - the number of vcpus 2498c2ecf20Sopenharmony_ci * The function is generally called when nr_spis has been explicitly set 2508c2ecf20Sopenharmony_ci * by the guest through the KVM DEVICE API. If not nr_spis is set to 256. 2518c2ecf20Sopenharmony_ci * vgic_initialized() returns true when this function has succeeded. 2528c2ecf20Sopenharmony_ci * Must be called with kvm->lock held! 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ciint vgic_init(struct kvm *kvm) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct vgic_dist *dist = &kvm->arch.vgic; 2578c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 2588c2ecf20Sopenharmony_ci int ret = 0, i, idx; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (vgic_initialized(kvm)) 2618c2ecf20Sopenharmony_ci return 0; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Are we also in the middle of creating a VCPU? */ 2648c2ecf20Sopenharmony_ci if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus)) 2658c2ecf20Sopenharmony_ci return -EBUSY; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* freeze the number of spis */ 2688c2ecf20Sopenharmony_ci if (!dist->nr_spis) 2698c2ecf20Sopenharmony_ci dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci ret = kvm_vgic_dist_init(kvm, dist->nr_spis); 2728c2ecf20Sopenharmony_ci if (ret) 2738c2ecf20Sopenharmony_ci goto out; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* Initialize groups on CPUs created before the VGIC type was known */ 2768c2ecf20Sopenharmony_ci kvm_for_each_vcpu(idx, vcpu, kvm) { 2778c2ecf20Sopenharmony_ci struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) { 2808c2ecf20Sopenharmony_ci struct vgic_irq *irq = &vgic_cpu->private_irqs[i]; 2818c2ecf20Sopenharmony_ci switch (dist->vgic_model) { 2828c2ecf20Sopenharmony_ci case KVM_DEV_TYPE_ARM_VGIC_V3: 2838c2ecf20Sopenharmony_ci irq->group = 1; 2848c2ecf20Sopenharmony_ci irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu); 2858c2ecf20Sopenharmony_ci break; 2868c2ecf20Sopenharmony_ci case KVM_DEV_TYPE_ARM_VGIC_V2: 2878c2ecf20Sopenharmony_ci irq->group = 0; 2888c2ecf20Sopenharmony_ci irq->targets = 1U << idx; 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci default: 2918c2ecf20Sopenharmony_ci ret = -EINVAL; 2928c2ecf20Sopenharmony_ci goto out; 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (vgic_has_its(kvm)) 2988c2ecf20Sopenharmony_ci vgic_lpi_translation_cache_init(kvm); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* 3018c2ecf20Sopenharmony_ci * If we have GICv4.1 enabled, unconditionnaly request enable the 3028c2ecf20Sopenharmony_ci * v4 support so that we get HW-accelerated vSGIs. Otherwise, only 3038c2ecf20Sopenharmony_ci * enable it if we present a virtual ITS to the guest. 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_ci if (vgic_supports_direct_msis(kvm)) { 3068c2ecf20Sopenharmony_ci ret = vgic_v4_init(kvm); 3078c2ecf20Sopenharmony_ci if (ret) 3088c2ecf20Sopenharmony_ci goto out; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) 3128c2ecf20Sopenharmony_ci kvm_vgic_vcpu_enable(vcpu); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci ret = kvm_vgic_setup_default_irq_routing(kvm); 3158c2ecf20Sopenharmony_ci if (ret) 3168c2ecf20Sopenharmony_ci goto out; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci vgic_debug_init(kvm); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci dist->implementation_rev = 2; 3218c2ecf20Sopenharmony_ci dist->initialized = true; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ciout: 3248c2ecf20Sopenharmony_ci return ret; 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic void kvm_vgic_dist_destroy(struct kvm *kvm) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci struct vgic_dist *dist = &kvm->arch.vgic; 3308c2ecf20Sopenharmony_ci struct vgic_redist_region *rdreg, *next; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci dist->ready = false; 3338c2ecf20Sopenharmony_ci dist->initialized = false; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci kfree(dist->spis); 3368c2ecf20Sopenharmony_ci dist->spis = NULL; 3378c2ecf20Sopenharmony_ci dist->nr_spis = 0; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { 3408c2ecf20Sopenharmony_ci list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) { 3418c2ecf20Sopenharmony_ci list_del(&rdreg->list); 3428c2ecf20Sopenharmony_ci kfree(rdreg); 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&dist->rd_regions); 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (vgic_has_its(kvm)) 3488c2ecf20Sopenharmony_ci vgic_lpi_translation_cache_destroy(kvm); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (vgic_supports_direct_msis(kvm)) 3518c2ecf20Sopenharmony_ci vgic_v4_teardown(kvm); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_civoid kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* 3598c2ecf20Sopenharmony_ci * Retire all pending LPIs on this vcpu anyway as we're 3608c2ecf20Sopenharmony_ci * going to destroy it. 3618c2ecf20Sopenharmony_ci */ 3628c2ecf20Sopenharmony_ci vgic_flush_pending_lpis(vcpu); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vgic_cpu->ap_list_head); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci/* To be called with kvm->lock held */ 3688c2ecf20Sopenharmony_cistatic void __kvm_vgic_destroy(struct kvm *kvm) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct kvm_vcpu *vcpu; 3718c2ecf20Sopenharmony_ci int i; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci vgic_debug_destroy(kvm); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) 3768c2ecf20Sopenharmony_ci kvm_vgic_vcpu_destroy(vcpu); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci kvm_vgic_dist_destroy(kvm); 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_civoid kvm_vgic_destroy(struct kvm *kvm) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 3848c2ecf20Sopenharmony_ci __kvm_vgic_destroy(kvm); 3858c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci/** 3898c2ecf20Sopenharmony_ci * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest 3908c2ecf20Sopenharmony_ci * is a GICv2. A GICv3 must be explicitly initialized by the guest using the 3918c2ecf20Sopenharmony_ci * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group. 3928c2ecf20Sopenharmony_ci * @kvm: kvm struct pointer 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_ciint vgic_lazy_init(struct kvm *kvm) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci int ret = 0; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (unlikely(!vgic_initialized(kvm))) { 3998c2ecf20Sopenharmony_ci /* 4008c2ecf20Sopenharmony_ci * We only provide the automatic initialization of the VGIC 4018c2ecf20Sopenharmony_ci * for the legacy case of a GICv2. Any other type must 4028c2ecf20Sopenharmony_ci * be explicitly initialized once setup with the respective 4038c2ecf20Sopenharmony_ci * KVM device call. 4048c2ecf20Sopenharmony_ci */ 4058c2ecf20Sopenharmony_ci if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2) 4068c2ecf20Sopenharmony_ci return -EBUSY; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 4098c2ecf20Sopenharmony_ci ret = vgic_init(kvm); 4108c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci return ret; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci/* RESOURCE MAPPING */ 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci/** 4198c2ecf20Sopenharmony_ci * Map the MMIO regions depending on the VGIC model exposed to the guest 4208c2ecf20Sopenharmony_ci * called on the first VCPU run. 4218c2ecf20Sopenharmony_ci * Also map the virtual CPU interface into the VM. 4228c2ecf20Sopenharmony_ci * v2/v3 derivatives call vgic_init if not already done. 4238c2ecf20Sopenharmony_ci * vgic_ready() returns true if this function has succeeded. 4248c2ecf20Sopenharmony_ci * @kvm: kvm struct pointer 4258c2ecf20Sopenharmony_ci */ 4268c2ecf20Sopenharmony_ciint kvm_vgic_map_resources(struct kvm *kvm) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci struct vgic_dist *dist = &kvm->arch.vgic; 4298c2ecf20Sopenharmony_ci int ret = 0; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci mutex_lock(&kvm->lock); 4328c2ecf20Sopenharmony_ci if (!irqchip_in_kernel(kvm)) 4338c2ecf20Sopenharmony_ci goto out; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) 4368c2ecf20Sopenharmony_ci ret = vgic_v2_map_resources(kvm); 4378c2ecf20Sopenharmony_ci else 4388c2ecf20Sopenharmony_ci ret = vgic_v3_map_resources(kvm); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci if (ret) 4418c2ecf20Sopenharmony_ci __kvm_vgic_destroy(kvm); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ciout: 4448c2ecf20Sopenharmony_ci mutex_unlock(&kvm->lock); 4458c2ecf20Sopenharmony_ci return ret; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci/* GENERIC PROBE */ 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int vgic_init_cpu_starting(unsigned int cpu) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0); 4538c2ecf20Sopenharmony_ci return 0; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic int vgic_init_cpu_dying(unsigned int cpu) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci disable_percpu_irq(kvm_vgic_global_state.maint_irq); 4608c2ecf20Sopenharmony_ci return 0; 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic irqreturn_t vgic_maintenance_handler(int irq, void *data) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci /* 4668c2ecf20Sopenharmony_ci * We cannot rely on the vgic maintenance interrupt to be 4678c2ecf20Sopenharmony_ci * delivered synchronously. This means we can only use it to 4688c2ecf20Sopenharmony_ci * exit the VM, and we perform the handling of EOIed 4698c2ecf20Sopenharmony_ci * interrupts on the exit path (see vgic_fold_lr_state). 4708c2ecf20Sopenharmony_ci */ 4718c2ecf20Sopenharmony_ci return IRQ_HANDLED; 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci/** 4758c2ecf20Sopenharmony_ci * kvm_vgic_init_cpu_hardware - initialize the GIC VE hardware 4768c2ecf20Sopenharmony_ci * 4778c2ecf20Sopenharmony_ci * For a specific CPU, initialize the GIC VE hardware. 4788c2ecf20Sopenharmony_ci */ 4798c2ecf20Sopenharmony_civoid kvm_vgic_init_cpu_hardware(void) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci BUG_ON(preemptible()); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* 4848c2ecf20Sopenharmony_ci * We want to make sure the list registers start out clear so that we 4858c2ecf20Sopenharmony_ci * only have the program the used registers. 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_ci if (kvm_vgic_global_state.type == VGIC_V2) 4888c2ecf20Sopenharmony_ci vgic_v2_init_lrs(); 4898c2ecf20Sopenharmony_ci else 4908c2ecf20Sopenharmony_ci kvm_call_hyp(__vgic_v3_init_lrs); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci/** 4948c2ecf20Sopenharmony_ci * kvm_vgic_hyp_init: populates the kvm_vgic_global_state variable 4958c2ecf20Sopenharmony_ci * according to the host GIC model. Accordingly calls either 4968c2ecf20Sopenharmony_ci * vgic_v2/v3_probe which registers the KVM_DEVICE that can be 4978c2ecf20Sopenharmony_ci * instantiated by a guest later on . 4988c2ecf20Sopenharmony_ci */ 4998c2ecf20Sopenharmony_ciint kvm_vgic_hyp_init(void) 5008c2ecf20Sopenharmony_ci{ 5018c2ecf20Sopenharmony_ci const struct gic_kvm_info *gic_kvm_info; 5028c2ecf20Sopenharmony_ci int ret; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci gic_kvm_info = gic_get_kvm_info(); 5058c2ecf20Sopenharmony_ci if (!gic_kvm_info) 5068c2ecf20Sopenharmony_ci return -ENODEV; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (!gic_kvm_info->maint_irq) { 5098c2ecf20Sopenharmony_ci kvm_err("No vgic maintenance irq\n"); 5108c2ecf20Sopenharmony_ci return -ENXIO; 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci switch (gic_kvm_info->type) { 5148c2ecf20Sopenharmony_ci case GIC_V2: 5158c2ecf20Sopenharmony_ci ret = vgic_v2_probe(gic_kvm_info); 5168c2ecf20Sopenharmony_ci break; 5178c2ecf20Sopenharmony_ci case GIC_V3: 5188c2ecf20Sopenharmony_ci ret = vgic_v3_probe(gic_kvm_info); 5198c2ecf20Sopenharmony_ci if (!ret) { 5208c2ecf20Sopenharmony_ci static_branch_enable(&kvm_vgic_global_state.gicv3_cpuif); 5218c2ecf20Sopenharmony_ci kvm_info("GIC system register CPU interface enabled\n"); 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci break; 5248c2ecf20Sopenharmony_ci default: 5258c2ecf20Sopenharmony_ci ret = -ENODEV; 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (ret) 5298c2ecf20Sopenharmony_ci return ret; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq; 5328c2ecf20Sopenharmony_ci ret = request_percpu_irq(kvm_vgic_global_state.maint_irq, 5338c2ecf20Sopenharmony_ci vgic_maintenance_handler, 5348c2ecf20Sopenharmony_ci "vgic", kvm_get_running_vcpus()); 5358c2ecf20Sopenharmony_ci if (ret) { 5368c2ecf20Sopenharmony_ci kvm_err("Cannot register interrupt %d\n", 5378c2ecf20Sopenharmony_ci kvm_vgic_global_state.maint_irq); 5388c2ecf20Sopenharmony_ci return ret; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci ret = cpuhp_setup_state(CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING, 5428c2ecf20Sopenharmony_ci "kvm/arm/vgic:starting", 5438c2ecf20Sopenharmony_ci vgic_init_cpu_starting, vgic_init_cpu_dying); 5448c2ecf20Sopenharmony_ci if (ret) { 5458c2ecf20Sopenharmony_ci kvm_err("Cannot register vgic CPU notifier\n"); 5468c2ecf20Sopenharmony_ci goto out_free_irq; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq); 5508c2ecf20Sopenharmony_ci return 0; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ciout_free_irq: 5538c2ecf20Sopenharmony_ci free_percpu_irq(kvm_vgic_global_state.maint_irq, 5548c2ecf20Sopenharmony_ci kvm_get_running_vcpus()); 5558c2ecf20Sopenharmony_ci return ret; 5568c2ecf20Sopenharmony_ci} 557