arm/arm64: KVM: pass down user space provided GIC type into vGIC code
authorAndre Przywara <andre.przywara@arm.com>
Tue, 3 Jun 2014 07:33:10 +0000 (09:33 +0200)
committerChristoffer Dall <christoffer.dall@linaro.org>
Tue, 20 Jan 2015 17:25:25 +0000 (18:25 +0100)
With the introduction of a second emulated GIC model we need to let
userspace specify the GIC model to use for each VM. Pass the
userspace provided value down into the vGIC code and store it there
to differentiate later.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
arch/arm/kvm/arm.c
include/kvm/arm_vgic.h
virt/kvm/arm/vgic.c

index a7b94ecba0d80616ad18201a8d2b8482d432f1a0..3a51ffca75e38ef803e2ff07ad196eae933705e2 100644 (file)
@@ -851,7 +851,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
        switch (ioctl) {
        case KVM_CREATE_IRQCHIP: {
                if (vgic_present)
-                       return kvm_vgic_create(kvm);
+                       return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
                else
                        return -ENXIO;
        }
index ac4888dc86bcb51d802cb08d1795c60d9c4180d3..525ce4228495b7bee90bbb998dcd1d2f822c6c61 100644 (file)
@@ -140,6 +140,9 @@ struct vgic_dist {
        bool                    in_kernel;
        bool                    ready;
 
+       /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+       u32                     vgic_model;
+
        int                     nr_cpus;
        int                     nr_irqs;
 
@@ -275,7 +278,7 @@ struct kvm_exit_mmio;
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 int kvm_vgic_hyp_init(void);
 int kvm_vgic_map_resources(struct kvm *kvm);
-int kvm_vgic_create(struct kvm *kvm);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
@@ -327,7 +330,7 @@ static inline int kvm_vgic_map_resources(struct kvm *kvm)
        return 0;
 }
 
-static inline int kvm_vgic_create(struct kvm *kvm)
+static inline int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
        return 0;
 }
index c84f53dfcd621faa082416048101ec384d5bff7b..283038e98d535cf04cd9d41bfe8919e715918219 100644 (file)
@@ -1698,6 +1698,16 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
        int vcpu_id;
 
        if (unlikely(!vgic_initialized(kvm))) {
+               /*
+                * We only provide the automatic initialization of the VGIC
+                * for the legacy case of a GICv2. Any other type must
+                * be explicitly initialized once setup with the respective
+                * KVM device call.
+                */
+               if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2) {
+                       ret = -EBUSY;
+                       goto out;
+               }
                mutex_lock(&kvm->lock);
                ret = vgic_init(kvm);
                mutex_unlock(&kvm->lock);
@@ -1935,7 +1945,7 @@ out:
        return ret;
 }
 
-int kvm_vgic_create(struct kvm *kvm)
+int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
        int i, vcpu_lock_idx = -1, ret;
        struct kvm_vcpu *vcpu;
@@ -1967,6 +1977,7 @@ int kvm_vgic_create(struct kvm *kvm)
 
        spin_lock_init(&kvm->arch.vgic.lock);
        kvm->arch.vgic.in_kernel = true;
+       kvm->arch.vgic.vgic_model = type;
        kvm->arch.vgic.vctrl_base = vgic->vctrl_base;
        kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
        kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
@@ -2404,7 +2415,7 @@ static void vgic_destroy(struct kvm_device *dev)
 
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
-       return kvm_vgic_create(dev->kvm);
+       return kvm_vgic_create(dev->kvm, type);
 }
 
 static struct kvm_device_ops kvm_arm_vgic_v2_ops = {