diff mbox series

[v2] KVM: X86: Introduce vfio_intr_stat per-vm debugfs file

Message ID 1644324020-17639-1-git-send-email-yuanzhaoxiong@baidu.com (mailing list archive)
State New, archived
Headers show
Series [v2] KVM: X86: Introduce vfio_intr_stat per-vm debugfs file | expand

Commit Message

Yuan ZhaoXiong Feb. 8, 2022, 12:40 p.m. UTC
Use this file to export correspondence between guest_irq, host_irq,
vector and vcpu belonging to VFIO passthrough devices.

An example output of this looks like (a vm with VFIO passthrough
devices):
   guest_irq     host_irq       vector         vcpu
          24          201           37            8
          25          202           35           25
          26          203           35           20
   ......

When a VM has VFIO passthrough devices, the correspondence between
guest_irq, host_irq, vector and vcpu may need to be known especially
in AMD platform with avic disabled. The AMD avic is disabled, and
the passthrough devices may cause vcpu vm exit twice for a interrupt.
One extrernal interrupt caused by vfio host irq, other ipi to inject
a interrupt to vm.

If the system administrator known these information, set vfio host
irq affinity to Pcpu which the correspondece guest irq affinited vcpu,
to avoid extra vm exit.

Co-developed-by: Li RongQing <lirongqing@baidu.com>
Signed-off-by: Li RongQing <lirongqing@baidu.com>
Signed-off-by: Yuan ZhaoXiong <yuanzhaoxiong@baidu.com>
---
v1: https://lore.kernel.org/lkml/1642593015-28729-1-git-send-email-yuanzhaoxiong@baidu.com/
v1->v2: 
- remove the HAVE_KVM_IRQ_BYPASS conditional judgment
- Modifying code format and remove unnecessary curly braces

 arch/x86/kvm/debugfs.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

Comments

Li RongQing Feb. 25, 2022, 2:27 a.m. UTC | #1
> 主题: [PATCH v2] KVM: X86: Introduce vfio_intr_stat per-vm debugfs file
> 
> Use this file to export correspondence between guest_irq, host_irq, vector and
> vcpu belonging to VFIO passthrough devices.
> 
> An example output of this looks like (a vm with VFIO passthrough
> devices):
>    guest_irq     host_irq       vector         vcpu
>           24          201           37            8
>           25          202           35           25
>           26          203           35           20
>    ......
> 
> When a VM has VFIO passthrough devices, the correspondence between
> guest_irq, host_irq, vector and vcpu may need to be known especially in AMD
> platform with avic disabled. The AMD avic is disabled, and the passthrough
> devices may cause vcpu vm exit twice for a interrupt.
> One extrernal interrupt caused by vfio host irq, other ipi to inject a interrupt to
> vm.
> 
> If the system administrator known these information, set vfio host irq affinity to
> Pcpu which the correspondece guest irq affinited vcpu, to avoid extra vm exit.
> 
> Co-developed-by: Li RongQing <lirongqing@baidu.com>
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> Signed-off-by: Yuan ZhaoXiong <yuanzhaoxiong@baidu.com>
> ---

Ping

Thanks

-Li
diff mbox series

Patch

diff --git a/arch/x86/kvm/debugfs.c b/arch/x86/kvm/debugfs.c
index 9240b3b..fef9014 100644
--- a/arch/x86/kvm/debugfs.c
+++ b/arch/x86/kvm/debugfs.c
@@ -6,6 +6,8 @@ 
  */
 #include <linux/kvm_host.h>
 #include <linux/debugfs.h>
+#include <linux/kvm_irqfd.h>
+#include <asm/irq_remapping.h>
 #include "lapic.h"
 #include "mmu.h"
 #include "mmu/mmu_internal.h"
@@ -181,9 +183,85 @@  static int kvm_mmu_rmaps_stat_release(struct inode *inode, struct file *file)
 	.release	= kvm_mmu_rmaps_stat_release,
 };
 
+static int kvm_vfio_intr_stat_show(struct seq_file *m, void *v)
+{
+	struct kvm_kernel_irq_routing_entry *e;
+	struct kvm_irq_routing_table *irq_rt;
+	unsigned int host_irq, guest_irq;
+	struct kvm_kernel_irqfd *irqfd;
+	struct kvm *kvm = m->private;
+	struct kvm_lapic_irq irq;
+	struct kvm_vcpu *vcpu;
+	int idx;
+
+	if (!kvm_arch_has_assigned_device(kvm) ||
+	    !irq_remapping_cap(IRQ_POSTING_CAP))
+		return 0;
+
+	seq_printf(m, "%12s %12s %12s %12s\n",
+		   "guest_irq", "host_irq", "vector", "vcpu");
+
+	spin_lock_irq(&kvm->irqfds.lock);
+	idx = srcu_read_lock(&kvm->irq_srcu);
+	irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
+
+	list_for_each_entry(irqfd, &kvm->irqfds.items, list) {
+		if (!irqfd->producer)
+			continue;
+
+		host_irq = irqfd->producer->irq;
+		guest_irq = irqfd->gsi;
+
+		if (guest_irq >= irq_rt->nr_rt_entries ||
+		    hlist_empty(&irq_rt->map[guest_irq]))
+			continue;
+
+		hlist_for_each_entry(e, &irq_rt->map[guest_irq], link) {
+			if (e->type != KVM_IRQ_ROUTING_MSI)
+				continue;
+
+			kvm_set_msi_irq(kvm, e, &irq);
+			if (kvm_intr_is_single_vcpu(kvm, &irq, &vcpu))
+				seq_printf(m, "%12u %12u %12u %12u\n",
+					   guest_irq, host_irq, irq.vector, vcpu->vcpu_id);
+		}
+	}
+	srcu_read_unlock(&kvm->irq_srcu, idx);
+	spin_unlock_irq(&kvm->irqfds.lock);
+	return 0;
+}
+
+static int kvm_vfio_intr_stat_open(struct inode *inode, struct file *file)
+{
+	struct kvm *kvm = inode->i_private;
+
+	if (!kvm_get_kvm_safe(kvm))
+		return -ENOENT;
+
+	return single_open(file, kvm_vfio_intr_stat_show, kvm);
+}
+
+static int kvm_vfio_intr_stat_release(struct inode *inode, struct file *file)
+{
+	struct kvm *kvm = inode->i_private;
+
+	kvm_put_kvm(kvm);
+	return single_release(inode, file);
+}
+
+static const struct file_operations vfio_intr_stat_fops = {
+	.open    = kvm_vfio_intr_stat_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = kvm_vfio_intr_stat_release,
+};
+
 int kvm_arch_create_vm_debugfs(struct kvm *kvm)
 {
 	debugfs_create_file("mmu_rmaps_stat", 0644, kvm->debugfs_dentry, kvm,
 			    &mmu_rmaps_stat_fops);
+
+	debugfs_create_file("vfio_intr_stat", 0444, kvm->debugfs_dentry, kvm,
+			    &vfio_intr_stat_fops);
 	return 0;
 }