Skip to contentSkip to conversation

GSI route layer for MSI/MSI-X

PATCH New Sheng Yang 1 participant 8 messages Jan 13, 2009 KVM

lore
Share & tools
lore

Sheng Yang

author
#0 lore raw

v6 cover GSI route layer for MSI/MSI-X

Update from v5:
Addressed Marcelo and Avi's comments, also change ioctl back to add/delete style one.

--
regards
Yang, Sheng

author
#1 lore raw

PATCH v6 1/7 KVM: Add a route layer to convert MSI message to GSI

Avi's purpose, to use single kvm_set_irq() to deal with all interrupt, including MSI. So here is it.

struct gsi_route_entry is a mapping from a special gsi(with KVM_GSI_MSG_ENTRY_MASK) to MSI/MSI-X message address/data. And the struct can also be extended for other purpose.

Now we support up to 128 gsi_route_entry mapping, and gsi is allocated by kernel and provide two ioctls to userspace, which is more flexiable.

---
 include/linux/kvm.h      |   24 +++++++++++++++
 include/linux/kvm_host.h |   22 +++++++++++++
 virt/kvm/irq_comm.c      |   74 ++++++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/kvm_main.c      |   65 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 185 insertions(+), 0 deletions(-)
include/linux/kvm.h +24 -0
index 71c150f..ba8ab1c 100644
@@ -399,6 +399,9 @@ struct kvm_trace_rec {
 #if defined(CONFIG_X86)
 #define KVM_CAP_REINJECT_CONTROL 24
 #endif
+#if defined(CONFIG_X86)
+#define KVM_CAP_GSI_ROUTE 25
+#endif
 
 /*
  * ioctls for VM fds
@@ -433,6 +436,10 @@ struct kvm_trace_rec {
 #define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \
 			    struct kvm_assigned_irq)
 #define KVM_REINJECT_CONTROL      _IO(KVMIO, 0x71)
+#define KVM_REQUEST_GSI_ROUTE	  _IOWR(KVMIO, 0x72, \
+					struct kvm_gsi_route_entry)
+#define KVM_FREE_GSI_ROUTE	  _IOR(KVMIO, 0x73, \
+					struct kvm_gsi_route_entry)
 
 /*
  * ioctls for vcpu fds
@@ -553,4 +560,21 @@ struct kvm_assigned_irq {
 #define KVM_DEV_IRQ_ASSIGN_MSI_ACTION	KVM_DEV_IRQ_ASSIGN_ENABLE_MSI
 #define KVM_DEV_IRQ_ASSIGN_ENABLE_MSI	(1 << 0)
 
+#define KVM_GSI_ROUTE_TYPE_MSI	0x1
+
+struct kvm_gsi_route_entry {
+	__u32 gsi;
+	__u32 type;
+	__u32 flags;
+	__u32 reserved;
+	union {
+		struct {
+			__u32 addr_lo;
+			__u32 addr_hi;
+			__u32 data;
+		} msi;
+		__u32 padding[8];
+	};
+};
+
 #endif
include/linux/kvm_host.h +22 -0
index a8bcad0..647a6bc 100644
@@ -136,6 +136,9 @@ struct kvm {
 	unsigned long mmu_notifier_seq;
 	long mmu_notifier_count;
 #endif
+	struct hlist_head gsi_route_list;
+#define KVM_NR_GSI_ROUTE_ENTRIES    128
+	DECLARE_BITMAP(gsi_route_bitmap, KVM_NR_GSI_ROUTE_ENTRIES);
 };
 
 /* The guest did something we don't support. */
@@ -336,6 +339,18 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
 				      struct kvm_irq_mask_notifier *kimn);
 void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask);
 
+#define KVM_GSI_ROUTE_ENTRY_MASK    0x1000000ull
+struct kvm_gsi_route_kernel_entry {
+	u32 gsi;
+	u32 type;
+	u32 flags;
+	u32 reserved;
+	union {
+		struct msi_msg msi;
+	};
+	struct hlist_node link;
+};
+
 void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
 void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
 void kvm_register_irq_ack_notifier(struct kvm *kvm,
@@ -343,6 +358,13 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,
 void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian);
 int kvm_request_irq_source_id(struct kvm *kvm);
 void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
+int kvm_update_gsi_route(struct kvm *kvm,
+			 struct kvm_gsi_route_kernel_entry *entry);
+struct kvm_gsi_route_kernel_entry *kvm_find_gsi_route_entry(struct kvm *kvm,
+							    u32 gsi);
+void kvm_free_gsi_route(struct kvm *kvm,
+			struct kvm_gsi_route_kernel_entry *entry);
+void kvm_free_gsi_route_list(struct kvm *kvm);
 
 #ifdef CONFIG_DMAR
 int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn,
virt/kvm/irq_comm.c +74 -0

77 lines not on this page · raw message

virt/kvm/kvm_main.c +65 -0

89 lines not on this page · raw message

Signature · 1 line
1.5.4.5
author
#2 lore raw

PATCH v6 2/7 KVM: Using gsi route for MSI device assignment

In reply to Sheng Yang

Convert MSI userspace interface to support gsi_msg mapping(and nobody should be the user of the old interface...).

---
 include/linux/kvm_host.h |    1 -
 virt/kvm/kvm_main.c      |   79 ++++++++++++++++++++++++++--------------------
 2 files changed, 45 insertions(+), 35 deletions(-)
include/linux/kvm_host.h +0 -1
index 647a6bc..8ba7dcf 100644
@@ -316,7 +316,6 @@ struct kvm_assigned_dev_kernel {
 	int host_irq;
 	bool host_irq_disabled;
 	int guest_irq;
-	struct msi_msg guest_msi;
 #define KVM_ASSIGNED_DEV_GUEST_INTX	(1 << 0)
 #define KVM_ASSIGNED_DEV_GUEST_MSI	(1 << 1)
 #define KVM_ASSIGNED_DEV_HOST_INTX	(1 << 8)
virt/kvm/kvm_main.c +45 -34

106 lines not on this page · raw message

Signature · 1 line
1.5.4.5
author
#3 lore raw

PATCH v6 3/7 KVM: Improve MSI dispatch function

In reply to Sheng Yang

Prepare to merge with kvm_set_irq().

---
 virt/kvm/kvm_main.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
virt/kvm/kvm_main.c +4 -4
index f3d5958..b0b97ba 100644
@@ -87,7 +87,7 @@ static bool kvm_rebooting;
 #ifdef KVM_CAP_DEVICE_ASSIGNMENT
 
 #ifdef CONFIG_X86
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi)
 {
 	int vcpu_id;
 	struct kvm_vcpu *vcpu;
@@ -98,7 +98,7 @@ static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
 
 	BUG_ON(!ioapic);
 
-	gsi_entry = kvm_find_gsi_route_entry(dev->kvm, dev->guest_irq);
+	gsi_entry = kvm_find_gsi_route_entry(dev->kvm, gsi);
 	if (!gsi_entry) {
 		printk(KERN_WARNING "kvm: fail to find correlated gsi entry\n");
 		return;
@@ -145,7 +145,7 @@ static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev)
 	}
 }
 #else
-static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev) {}
+static void assigned_device_msi_dispatch(struct kvm_assigned_dev_kernel *dev, u32 gsi) {}
 #endif
 
 static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
@@ -180,7 +180,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
 			    assigned_dev->guest_irq, 1);
 	else if (assigned_dev->irq_requested_type &
 				KVM_ASSIGNED_DEV_GUEST_MSI) {
-		assigned_device_msi_dispatch(assigned_dev);
+		assigned_device_msi_dispatch(assigned_dev, assigned_dev->guest_irq);
 		enable_irq(assigned_dev->host_irq);
 		assigned_dev->host_irq_disabled = false;
 	}
Signature · 1 line
1.5.4.5
author
#4 lore raw

PATCH v6 4/7 KVM: Using ioapic_irqchip() macro for kvm_set_irq

In reply to Sheng Yang
---
 virt/kvm/irq_comm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
virt/kvm/irq_comm.c +1 -1
index 8f49113..0c3266a 100644
@@ -39,7 +39,7 @@ void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
 	 * IOAPIC.  So set the bit in both. The guest will ignore
 	 * writes to the unused one.
 	 */
-	kvm_ioapic_set_irq(kvm->arch.vioapic, irq, !!(*irq_state));
+	kvm_ioapic_set_irq(ioapic_irqchip(kvm), irq, !!(*irq_state));
 #ifdef CONFIG_X86
 	kvm_pic_set_irq(pic_irqchip(kvm), irq, !!(*irq_state));
 #endif
Signature · 1 line
1.5.4.5
author
#5 lore raw

PATCH v6 5/7 KVM: Merge MSI handling to kvm_set_irq

In reply to Sheng Yang

Using kvm_set_irq to handle all interrupt injection.

---
 include/linux/kvm_host.h |    2 +-
 virt/kvm/irq_comm.c      |   79 +++++++++++++++++++++++++++++++++++++++++++--
 virt/kvm/kvm_main.c      |   78 +++------------------------------------------
 3 files changed, 81 insertions(+), 78 deletions(-)
include/linux/kvm_host.h +1 -1
index 8ba7dcf..440409f 100644
@@ -350,7 +350,7 @@ struct kvm_gsi_route_kernel_entry {
 	struct hlist_node link;
 };
 
-void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level);
+void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level);
 void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
 void kvm_register_irq_ack_notifier(struct kvm *kvm,
 				   struct kvm_irq_ack_notifier *kian);
virt/kvm/irq_comm.c +75 -4

94 lines not on this page · raw message

virt/kvm/kvm_main.c +5 -73

96 lines not on this page · raw message

Signature · 1 line
1.5.4.5
author
#6 lore raw

PATCH v6 6/7 KVM: Split IOAPIC structure

In reply to Sheng Yang

Prepared for reuse ioapic_redir_entry for MSI.

---
 include/linux/kvm_types.h |   17 +++++++++++++++++
 virt/kvm/ioapic.c         |    6 +++---
 virt/kvm/ioapic.h         |   17 +----------------
 3 files changed, 21 insertions(+), 19 deletions(-)
include/linux/kvm_types.h +17 -0
index 5f4a18c..46e3d8d 100644
@@ -52,4 +52,21 @@ struct kvm_pio_request {
 	int rep;
 };
 
+union kvm_ioapic_redirect_entry {
+	u64 bits;
+	struct {
+		u8 vector;
+		u8 delivery_mode:3;
+		u8 dest_mode:1;
+		u8 delivery_status:1;
+		u8 polarity:1;
+		u8 remote_irr:1;
+		u8 trig_mode:1;
+		u8 mask:1;
+		u8 reserve:7;
+		u8 reserved[4];
+		u8 dest_id;
+	} fields;
+};
+
 #endif /* __KVM_TYPES_H__ */
virt/kvm/ioapic.c +3 -3
index e85a2bc..b6530e9 100644
@@ -85,7 +85,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
 
 static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
 {
-	union ioapic_redir_entry *pent;
+	union kvm_ioapic_redirect_entry *pent;
 
 	pent = &ioapic->redirtbl[idx];
 
@@ -277,7 +277,7 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
 {
 	u32 old_irr = ioapic->irr;
 	u32 mask = 1 << irq;
-	union ioapic_redir_entry entry;
+	union kvm_ioapic_redirect_entry entry;
 
 	if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
 		entry = ioapic->redirtbl[irq];
@@ -296,7 +296,7 @@ void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
 static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi,
 				    int trigger_mode)
 {
-	union ioapic_redir_entry *ent;
+	union kvm_ioapic_redirect_entry *ent;
 
 	ent = &ioapic->redirtbl[gsi];
 
virt/kvm/ioapic.h +1 -16
index 49c9581..ee5b0bd 100644
@@ -40,22 +40,7 @@ struct kvm_ioapic {
 	u32 id;
 	u32 irr;
 	u32 pad;
-	union ioapic_redir_entry {
-		u64 bits;
-		struct {
-			u8 vector;
-			u8 delivery_mode:3;
-			u8 dest_mode:1;
-			u8 delivery_status:1;
-			u8 polarity:1;
-			u8 remote_irr:1;
-			u8 trig_mode:1;
-			u8 mask:1;
-			u8 reserve:7;
-			u8 reserved[4];
-			u8 dest_id;
-		} fields;
-	} redirtbl[IOAPIC_NUM_PINS];
+	union kvm_ioapic_redirect_entry redirtbl[IOAPIC_NUM_PINS];
 	struct kvm_io_device dev;
 	struct kvm *kvm;
 	void (*ack_notifier)(void *opaque, int irq);
Signature · 1 line
1.5.4.5
author
#7 lore raw

PATCH v6 7/7 KVM: Unified the delivery of IOAPIC and MSI

In reply to Sheng Yang
---
 include/linux/kvm_host.h |    3 ++
 virt/kvm/ioapic.c        |   84 ++++++++++++++++----------------------------
 virt/kvm/irq_comm.c      |   87 ++++++++++++++++++++++++++++------------------
 3 files changed, 87 insertions(+), 87 deletions(-)
include/linux/kvm_host.h +3 -0
index 440409f..b0d5a95 100644
@@ -350,6 +350,9 @@ struct kvm_gsi_route_kernel_entry {
 	struct hlist_node link;
 };
 
+void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic,
+				   union kvm_ioapic_redirect_entry *entry,
+				   u32 *deliver_bitmask);
 void kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 gsi, int level);
 void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi);
 void kvm_register_irq_ack_notifier(struct kvm *kvm,
virt/kvm/ioapic.c +31 -53

106 lines not on this page · raw message

virt/kvm/irq_comm.c +53 -34

108 lines not on this page · raw message

Signature · 1 line
1.5.4.5