[PATCH 20/23] KVM: arm64: Move irqfd routing to irqchip_flow

Marc Zyngier maz at kernel.org
Thu Sep 3 11:26:07 EDT 2020


irqfd handling is still hidden away in the vgic code. Let's
extract it and move the generic part in the non-GIC code,
with the now required abstraction in the irqchip_flow struct.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/include/asm/kvm_irq.h | 11 +++++
 arch/arm64/kvm/arm.c             | 68 ++++++++++++++++++++++++++++++
 arch/arm64/kvm/vgic/vgic-init.c  |  3 ++
 arch/arm64/kvm/vgic/vgic-irqfd.c | 72 ++++++--------------------------
 arch/arm64/kvm/vgic/vgic.h       | 10 +++++
 5 files changed, 104 insertions(+), 60 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_irq.h b/arch/arm64/include/asm/kvm_irq.h
index 649b7d4c7e9f..05fbe5241642 100644
--- a/arch/arm64/include/asm/kvm_irq.h
+++ b/arch/arm64/include/asm/kvm_irq.h
@@ -19,6 +19,8 @@ enum kvm_irqchip_type {
 
 #define irqchip_finalized(k)	((k)->arch.irqchip_finalized)
 
+struct kvm_kernel_irq_routing_entry;
+
 struct kvm_irqchip_flow {
 	void (*irqchip_destroy)(struct kvm *);
 	int  (*irqchip_vcpu_init)(struct kvm_vcpu *);
@@ -41,6 +43,15 @@ struct kvm_irqchip_flow {
 				     u32, bool (*)(int));
 	int  (*irqchip_unmap_phys_irq)(struct kvm_vcpu *, unsigned int);
 	int  (*irqchip_set_owner)(struct kvm_vcpu *, unsigned int, void *);
+	int  (*irqchip_irqfd_set_irq)(struct kvm_kernel_irq_routing_entry *e,
+				      struct kvm *kvm, int irq_source_id,
+				      int level, bool line_status);
+	int  (*irqchip_set_msi)(struct kvm_kernel_irq_routing_entry *e,
+				struct kvm *kvm, int irq_source_id,
+				int level, bool line_status);
+	int  (*irqchip_set_irq_inatomic)(struct kvm_kernel_irq_routing_entry *e,
+					 struct kvm *kvm, int irq_source_id,
+					 int level, bool line_status);
 };
 
 /*
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 678533871cfa..d625904633c0 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1592,6 +1592,74 @@ void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *cons)
 	kvm_arm_resume_guest(irqfd->kvm);
 }
 
+/**
+ * kvm_set_routing_entry: populate a kvm routing entry
+ * from a user routing entry
+ *
+ * @kvm: the VM this entry is applied to
+ * @e: kvm kernel routing entry handle
+ * @ue: user api routing entry handle
+ * return 0 on success, -EINVAL on errors.
+ */
+int kvm_set_routing_entry(struct kvm *kvm,
+			  struct kvm_kernel_irq_routing_entry *e,
+			  const struct kvm_irq_routing_entry *ue)
+{
+	int r = -EINVAL;
+
+	switch (ue->type) {
+	case KVM_IRQ_ROUTING_IRQCHIP:
+		e->set = kvm->arch.irqchip_flow.irqchip_irqfd_set_irq;
+		e->irqchip.irqchip = ue->u.irqchip.irqchip;
+		e->irqchip.pin = ue->u.irqchip.pin;
+		if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
+		    (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
+			goto out;
+		break;
+	case KVM_IRQ_ROUTING_MSI:
+		e->set = kvm->arch.irqchip_flow.irqchip_set_msi;
+		e->msi.address_lo = ue->u.msi.address_lo;
+		e->msi.address_hi = ue->u.msi.address_hi;
+		e->msi.data = ue->u.msi.data;
+		e->msi.flags = ue->flags;
+		e->msi.devid = ue->u.msi.devid;
+		break;
+	default:
+		goto out;
+	}
+
+	if (!e->set)
+		goto out;
+
+	r = 0;
+out:
+	return r;
+}
+
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		struct kvm *kvm, int irq_source_id,
+		int level, bool line_status)
+{
+	if (!kvm->arch.irqchip_flow.irqchip_set_msi)
+		return -ENODEV;
+	return kvm->arch.irqchip_flow.irqchip_set_msi(e, kvm, irq_source_id,
+						      level, line_status);
+}
+
+int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
+			      struct kvm *kvm, int irq_source_id, int level,
+			      bool line_status)
+{
+	if (!level || !irqchip_finalized(kvm) ||
+	    !kvm->arch.irqchip_flow.irqchip_set_irq_inatomic)
+		return -EWOULDBLOCK;
+
+	return kvm->arch.irqchip_flow.irqchip_set_irq_inatomic(e, kvm,
+							       irq_source_id,
+							       level,
+							       line_status);
+}
+
 /**
  * Initialize Hyp-mode and memory mappings on all CPUs.
  */
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index a3e0389617a3..440b8c09c030 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -34,6 +34,9 @@ static struct kvm_irqchip_flow vgic_irqchip_flow = {
 	.irqchip_map_phys_irq		= kvm_vgic_map_phys_irq,
 	.irqchip_unmap_phys_irq		= kvm_vgic_unmap_phys_irq,
 	.irqchip_set_owner		= kvm_vgic_set_owner,
+	.irqchip_irqfd_set_irq		= vgic_irqfd_set_irq,
+	.irqchip_set_msi		= vgic_set_msi,
+	.irqchip_set_irq_inatomic	= vgic_set_irq_inatomic,
 };
 
 /*
diff --git a/arch/arm64/kvm/vgic/vgic-irqfd.c b/arch/arm64/kvm/vgic/vgic-irqfd.c
index dbece60c8dc0..5bbdfe982a00 100644
--- a/arch/arm64/kvm/vgic/vgic-irqfd.c
+++ b/arch/arm64/kvm/vgic/vgic-irqfd.c
@@ -15,9 +15,9 @@
  *
  * This is the entry point for irqfd IRQ injection
  */
-static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
-			struct kvm *kvm, int irq_source_id,
-			int level, bool line_status)
+int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
+		       struct kvm *kvm, int irq_source_id,
+		       int level, bool line_status)
 {
 	unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
 
@@ -26,46 +26,6 @@ static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
 	return kvm_vgic_inject_irq(kvm, 0, spi_id, level, NULL);
 }
 
-/**
- * kvm_set_routing_entry: populate a kvm routing entry
- * from a user routing entry
- *
- * @kvm: the VM this entry is applied to
- * @e: kvm kernel routing entry handle
- * @ue: user api routing entry handle
- * return 0 on success, -EINVAL on errors.
- */
-int kvm_set_routing_entry(struct kvm *kvm,
-			  struct kvm_kernel_irq_routing_entry *e,
-			  const struct kvm_irq_routing_entry *ue)
-{
-	int r = -EINVAL;
-
-	switch (ue->type) {
-	case KVM_IRQ_ROUTING_IRQCHIP:
-		e->set = vgic_irqfd_set_irq;
-		e->irqchip.irqchip = ue->u.irqchip.irqchip;
-		e->irqchip.pin = ue->u.irqchip.pin;
-		if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
-		    (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
-			goto out;
-		break;
-	case KVM_IRQ_ROUTING_MSI:
-		e->set = kvm_set_msi;
-		e->msi.address_lo = ue->u.msi.address_lo;
-		e->msi.address_hi = ue->u.msi.address_hi;
-		e->msi.data = ue->u.msi.data;
-		e->msi.flags = ue->flags;
-		e->msi.devid = ue->u.msi.devid;
-		break;
-	default:
-		goto out;
-	}
-	r = 0;
-out:
-	return r;
-}
-
 static void kvm_populate_msi(struct kvm_kernel_irq_routing_entry *e,
 			     struct kvm_msi *msi)
 {
@@ -75,16 +35,17 @@ static void kvm_populate_msi(struct kvm_kernel_irq_routing_entry *e,
 	msi->flags = e->msi.flags;
 	msi->devid = e->msi.devid;
 }
+
 /**
- * kvm_set_msi: inject the MSI corresponding to the
+ * vgic_set_msi: inject the MSI corresponding to the
  * MSI routing entry
  *
  * This is the entry point for irqfd MSI injection
  * and userspace MSI injection.
  */
-int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-		struct kvm *kvm, int irq_source_id,
-		int level, bool line_status)
+int vgic_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		 struct kvm *kvm, int irq_source_id,
+		 int level, bool line_status)
 {
 	struct kvm_msi msi;
 
@@ -99,15 +60,12 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
 }
 
 /**
- * kvm_arch_set_irq_inatomic: fast-path for irqfd injection
+ * vgic_set_irq_inatomic: fast-path for irqfd injection
  */
-int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
-			      struct kvm *kvm, int irq_source_id, int level,
-			      bool line_status)
+int vgic_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
+			  struct kvm *kvm, int irq_source_id, int level,
+			  bool line_status)
 {
-	if (!level)
-		return -EWOULDBLOCK;
-
 	switch (e->type) {
 	case KVM_IRQ_ROUTING_MSI: {
 		struct kvm_msi msi;
@@ -120,12 +78,6 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
 	}
 
 	case KVM_IRQ_ROUTING_IRQCHIP:
-		/*
-		 * Injecting SPIs is always possible in atomic context
-		 * as long as the damn vgic is initialized.
-		 */
-		if (unlikely(!irqchip_finalized(kvm)))
-			break;
 		return vgic_irqfd_set_irq(e, kvm, irq_source_id, 1, line_status);
 	}
 
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index c9e14a6cddf6..db3b111ed611 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -324,6 +324,16 @@ void vgic_lpi_translation_cache_init(struct kvm *kvm);
 void vgic_lpi_translation_cache_destroy(struct kvm *kvm);
 void vgic_its_invalidate_cache(struct kvm *kvm);
 
+int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
+		       struct kvm *kvm, int irq_source_id,
+		       int level, bool line_status);
+int vgic_set_msi(struct kvm_kernel_irq_routing_entry *e,
+		 struct kvm *kvm, int irq_source_id,
+		 int level, bool line_status);
+int vgic_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
+			  struct kvm *kvm, int irq_source_id, int level,
+			  bool line_status);
+
 bool vgic_supports_direct_msis(struct kvm *kvm);
 int vgic_v4_init(struct kvm *kvm);
 void vgic_v4_teardown(struct kvm *kvm);
-- 
2.27.0




More information about the linux-arm-kernel mailing list