diff options
| author | Eric Auger <eric.auger@linaro.org> | 2015-12-21 08:50:50 -0500 |
|---|---|---|
| committer | Christoffer Dall <christoffer.dall@linaro.org> | 2016-05-20 09:40:06 -0400 |
| commit | 5e6431da8f3a04759ac8d77b7c98eec0de580343 (patch) | |
| tree | 05427daf31565c48c3dd2184a0dd8ccaaceb33aa /virt | |
| parent | 909777324588b40d431e6e3af0911ee62e0d00e3 (diff) | |
KVM: arm/arm64: vgic-new: vgic_init: implement vgic_create
This patch implements the vgic_creation function which is
called on CREATE_IRQCHIP VM IOCTL (v2 only) or KVM_CREATE_DEVICE
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-init.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index 4523beb029f3..15d54284305b 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c | |||
| @@ -22,6 +22,90 @@ | |||
| 22 | #include <asm/kvm_mmu.h> | 22 | #include <asm/kvm_mmu.h> |
| 23 | #include "vgic.h" | 23 | #include "vgic.h" |
| 24 | 24 | ||
| 25 | /* CREATION */ | ||
| 26 | |||
| 27 | /** | ||
| 28 | * kvm_vgic_create: triggered by the instantiation of the VGIC device by | ||
| 29 | * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only) | ||
| 30 | * or through the generic KVM_CREATE_DEVICE API ioctl. | ||
| 31 | * irqchip_in_kernel() tells you if this function succeeded or not. | ||
| 32 | */ | ||
| 33 | int kvm_vgic_create(struct kvm *kvm, u32 type) | ||
| 34 | { | ||
| 35 | int i, vcpu_lock_idx = -1, ret; | ||
| 36 | struct kvm_vcpu *vcpu; | ||
| 37 | |||
| 38 | mutex_lock(&kvm->lock); | ||
| 39 | |||
| 40 | if (irqchip_in_kernel(kvm)) { | ||
| 41 | ret = -EEXIST; | ||
| 42 | goto out; | ||
| 43 | } | ||
| 44 | |||
| 45 | /* | ||
| 46 | * This function is also called by the KVM_CREATE_IRQCHIP handler, | ||
| 47 | * which had no chance yet to check the availability of the GICv2 | ||
| 48 | * emulation. So check this here again. KVM_CREATE_DEVICE does | ||
| 49 | * the proper checks already. | ||
| 50 | */ | ||
| 51 | if (type == KVM_DEV_TYPE_ARM_VGIC_V2 && | ||
| 52 | !kvm_vgic_global_state.can_emulate_gicv2) { | ||
| 53 | ret = -ENODEV; | ||
| 54 | goto out; | ||
| 55 | } | ||
| 56 | |||
| 57 | /* | ||
| 58 | * Any time a vcpu is run, vcpu_load is called which tries to grab the | ||
| 59 | * vcpu->mutex. By grabbing the vcpu->mutex of all VCPUs we ensure | ||
| 60 | * that no other VCPUs are run while we create the vgic. | ||
| 61 | */ | ||
| 62 | ret = -EBUSY; | ||
| 63 | kvm_for_each_vcpu(i, vcpu, kvm) { | ||
| 64 | if (!mutex_trylock(&vcpu->mutex)) | ||
| 65 | goto out_unlock; | ||
| 66 | vcpu_lock_idx = i; | ||
| 67 | } | ||
| 68 | |||
| 69 | kvm_for_each_vcpu(i, vcpu, kvm) { | ||
| 70 | if (vcpu->arch.has_run_once) | ||
| 71 | goto out_unlock; | ||
| 72 | } | ||
| 73 | ret = 0; | ||
| 74 | |||
| 75 | if (type == KVM_DEV_TYPE_ARM_VGIC_V2) | ||
| 76 | kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS; | ||
| 77 | else | ||
| 78 | kvm->arch.max_vcpus = VGIC_V3_MAX_CPUS; | ||
| 79 | |||
| 80 | if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) { | ||
| 81 | ret = -E2BIG; | ||
| 82 | goto out_unlock; | ||
| 83 | } | ||
| 84 | |||
| 85 | kvm->arch.vgic.in_kernel = true; | ||
| 86 | kvm->arch.vgic.vgic_model = type; | ||
| 87 | |||
| 88 | /* | ||
| 89 | * kvm_vgic_global_state.vctrl_base is set on vgic probe (kvm_arch_init) | ||
| 90 | * it is stored in distributor struct for asm save/restore purpose | ||
| 91 | */ | ||
| 92 | kvm->arch.vgic.vctrl_base = kvm_vgic_global_state.vctrl_base; | ||
| 93 | |||
| 94 | kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; | ||
| 95 | kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; | ||
| 96 | kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF; | ||
| 97 | |||
| 98 | out_unlock: | ||
| 99 | for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) { | ||
| 100 | vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx); | ||
| 101 | mutex_unlock(&vcpu->mutex); | ||
| 102 | } | ||
| 103 | |||
| 104 | out: | ||
| 105 | mutex_unlock(&kvm->lock); | ||
| 106 | return ret; | ||
| 107 | } | ||
| 108 | |||
| 25 | /* GENERIC PROBE */ | 109 | /* GENERIC PROBE */ |
| 26 | 110 | ||
| 27 | static void vgic_init_maintenance_interrupt(void *info) | 111 | static void vgic_init_maintenance_interrupt(void *info) |
