]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
KVM: arm/arm64: Check if irq lines to the GIC are already used
authorChristoffer Dall <cdall@linaro.org>
Thu, 4 May 2017 11:32:53 +0000 (13:32 +0200)
committerChristoffer Dall <cdall@linaro.org>
Thu, 8 Jun 2017 15:00:12 +0000 (17:00 +0200)
We check if other in-kernel devices have already been connected to the
GIC for a particular interrupt line when possible.

For the PMU, we can do this whenever setting the PMU interrupt number
from userspace.

For the timers, we have to wait until we try to enable the timer,
because we have a concept of default IRQ numbers that userspace
shouldn't have to work around in the initialization phase.

Signed-off-by: Christoffer Dall <cdall@linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
virt/kvm/arm/arch_timer.c
virt/kvm/arm/pmu.c

index e03da1abd11f5a72f7708a8dc502e615b2d11632..07f6f9bfc1f2e64ff2f82fc9072d74ad79741e19 100644 (file)
@@ -618,20 +618,22 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
        kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq);
 }
 
-static bool timer_irqs_are_valid(struct kvm *kvm)
+static bool timer_irqs_are_valid(struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu *vcpu;
        int vtimer_irq, ptimer_irq;
-       int i;
+       int i, ret;
 
-       vcpu = kvm_get_vcpu(kvm, 0);
        vtimer_irq = vcpu_vtimer(vcpu)->irq.irq;
-       ptimer_irq = vcpu_ptimer(vcpu)->irq.irq;
+       ret = kvm_vgic_set_owner(vcpu, vtimer_irq, vcpu_vtimer(vcpu));
+       if (ret)
+               return false;
 
-       if (vtimer_irq == ptimer_irq)
+       ptimer_irq = vcpu_ptimer(vcpu)->irq.irq;
+       ret = kvm_vgic_set_owner(vcpu, ptimer_irq, vcpu_ptimer(vcpu));
+       if (ret)
                return false;
 
-       kvm_for_each_vcpu(i, vcpu, kvm) {
+       kvm_for_each_vcpu(i, vcpu, vcpu->kvm) {
                if (vcpu_vtimer(vcpu)->irq.irq != vtimer_irq ||
                    vcpu_ptimer(vcpu)->irq.irq != ptimer_irq)
                        return false;
@@ -659,7 +661,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
        if (!vgic_initialized(vcpu->kvm))
                return -ENODEV;
 
-       if (!timer_irqs_are_valid(vcpu->kvm)) {
+       if (!timer_irqs_are_valid(vcpu)) {
                kvm_debug("incorrectly configured timer irqs\n");
                return -EINVAL;
        }
index 574feff55a6cfd2829d44ac859d6a6f80b40ae99..3f0866925b6bb40ddc061954643cb42eaa22df1e 100644 (file)
@@ -480,6 +480,8 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
                return -EBUSY;
 
        if (irqchip_in_kernel(vcpu->kvm)) {
+               int ret;
+
                /*
                 * If using the PMU with an in-kernel virtual GIC
                 * implementation, we require the GIC to be already
@@ -490,6 +492,11 @@ static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
 
                if (!kvm_arm_pmu_irq_initialized(vcpu))
                        return -ENXIO;
+
+               ret = kvm_vgic_set_owner(vcpu, vcpu->arch.pmu.irq_num,
+                                        &vcpu->arch.pmu);
+               if (ret)
+                       return ret;
        }
 
        vcpu->arch.pmu.created = true;