GSI route layer for MSI/MSI-X
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
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
@@ -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
@@ -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
PATCH v6 2/7 KVM: Using gsi route for MSI device assignment
In reply to Sheng YangConvert 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
@@ -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
PATCH v6 3/7 KVM: Improve MSI dispatch function
In reply to Sheng YangPrepare 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
@@ -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
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
@@ -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
PATCH v6 5/7 KVM: Merge MSI handling to kvm_set_irq
In reply to Sheng YangUsing 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
@@ -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
PATCH v6 6/7 KVM: Split IOAPIC structure
In reply to Sheng YangPrepared 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
@@ -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
@@ -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
@@ -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
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
@@ -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