|
@@ -312,6 +312,47 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
|
|
return vgic_update_irq_pending(kvm, cpuid, intid, level, false);
|
|
|
}
|
|
|
|
|
|
+int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
|
|
+ bool level)
|
|
|
+{
|
|
|
+ return vgic_update_irq_pending(kvm, cpuid, intid, level, true);
|
|
|
+}
|
|
|
+
|
|
|
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
|
|
|
+{
|
|
|
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
|
|
|
+
|
|
|
+ BUG_ON(!irq);
|
|
|
+
|
|
|
+ spin_lock(&irq->irq_lock);
|
|
|
+
|
|
|
+ irq->hw = true;
|
|
|
+ irq->hwintid = phys_irq;
|
|
|
+
|
|
|
+ spin_unlock(&irq->irq_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
|
|
|
+{
|
|
|
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
|
|
|
+
|
|
|
+ BUG_ON(!irq);
|
|
|
+
|
|
|
+ if (!vgic_initialized(vcpu->kvm))
|
|
|
+ return -EAGAIN;
|
|
|
+
|
|
|
+ spin_lock(&irq->irq_lock);
|
|
|
+
|
|
|
+ irq->hw = false;
|
|
|
+ irq->hwintid = 0;
|
|
|
+
|
|
|
+ spin_unlock(&irq->irq_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* vgic_prune_ap_list - Remove non-relevant interrupts from the list
|
|
|
*
|
|
@@ -564,3 +605,15 @@ void vgic_kick_vcpus(struct kvm *kvm)
|
|
|
kvm_vcpu_kick(vcpu);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
|
|
|
+{
|
|
|
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
|
|
|
+ bool map_is_active;
|
|
|
+
|
|
|
+ spin_lock(&irq->irq_lock);
|
|
|
+ map_is_active = irq->hw && irq->active;
|
|
|
+ spin_unlock(&irq->irq_lock);
|
|
|
+
|
|
|
+ return map_is_active;
|
|
|
+}
|