It turns out that having these debugfs information is really
useful when trying to understand what is going wrong in a
guest, or even in the host kernel...

Signed-off-by: Marc Zyngier <m...@kernel.org>
---
 arch/arm64/kvm/rvic-cpu.c | 140 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/arch/arm64/kvm/rvic-cpu.c b/arch/arm64/kvm/rvic-cpu.c
index 5fb200c637d9..0e91bf6633d5 100644
--- a/arch/arm64/kvm/rvic-cpu.c
+++ b/arch/arm64/kvm/rvic-cpu.c
@@ -6,6 +6,7 @@
  * Author: Marc Zyngier <m...@kernel.org>
  */
 
+#include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/kvm_host.h>
 #include <linux/list.h>
@@ -707,6 +708,8 @@ static int rvic_inject_userspace_irq(struct kvm *kvm, 
unsigned int type,
        }
 }
 
+static void rvic_create_debugfs(struct kvm_vcpu *vcpu);
+
 static int rvic_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct rvic_vm_data *data = vcpu->kvm->arch.irqchip_data;
@@ -743,6 +746,8 @@ static int rvic_vcpu_init(struct kvm_vcpu *vcpu)
                irq->line_level         = false;
        }
 
+       rvic_create_debugfs(vcpu);
+
        return 0;
 }
 
@@ -913,6 +918,8 @@ static void rvic_device_destroy(struct kvm_device *dev)
        kfree(dev);
 }
 
+static void rvid_create_debugfs(struct kvm *kvm);
+
 static int rvic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
 {
        struct rvic_vm_data *data;
@@ -969,6 +976,7 @@ static int rvic_set_attr(struct kvm_device *dev, struct 
kvm_device_attr *attr)
                }
 
                dev->kvm->arch.irqchip_data = data;
+               rvid_create_debugfs(dev->kvm);
 
                ret = 0;
                break;
@@ -1071,3 +1079,135 @@ int kvm_register_rvic_device(void)
 {
        return kvm_register_device_ops(&rvic_dev_ops, KVM_DEV_TYPE_ARM_RVIC);
 }
+
+static void rvic_irq_debug_show_one(struct seq_file *s, struct rvic_irq *irq)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&irq->lock, flags);
+
+       seq_printf(s, "%d: [%d] %c %c %ps %c %c\n",
+                  irq->intid, irq->host_irq,
+                  irq->pending ? 'P' : 'p',
+                  irq->masked ? 'M' : 'm',
+                  irq->get_line_level,
+                  irq->get_line_level ? 'x' : (irq->line_level ? 'H' : 'L'),
+                  rvic_irq_queued(irq) ? 'Q' : 'i');
+
+       spin_unlock_irqrestore(&irq->lock, flags);
+}
+
+static int rvic_irq_debug_show(struct seq_file *s, void *p)
+{
+       rvic_irq_debug_show_one(s, s->private);
+       return 0;
+}
+
+static int rvic_irq_debug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rvic_irq_debug_show, inode->i_private);
+}
+
+static const struct file_operations rvic_irq_debug_fops = {
+       .open           = rvic_irq_debug_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int rvic_debug_show(struct seq_file *s, void *p)
+{
+       struct kvm_vcpu *vcpu = s->private;
+       struct rvic *rvic = kvm_vcpu_to_rvic(vcpu);
+       struct rvic_irq *irq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rvic->lock, flags);
+
+       seq_printf(s, "%s\n", rvic->enabled ? "Enabled" : "Disabled");
+       seq_printf(s, "%d Trusted\n", rvic->nr_trusted);
+       seq_printf(s, "%d Total\n", rvic->nr_total);
+       list_for_each_entry(irq, &rvic->delivery, delivery_entry)
+               rvic_irq_debug_show_one(s, irq);
+
+       spin_unlock_irqrestore(&rvic->lock, flags);
+
+       return 0;
+}
+
+static int rvic_debug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rvic_debug_show, inode->i_private);
+}
+
+static const struct file_operations rvic_debug_fops = {
+       .open           = rvic_debug_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void rvic_create_debugfs(struct kvm_vcpu *vcpu)
+{
+       struct rvic *rvic = kvm_vcpu_to_rvic(vcpu);
+       struct dentry *rvic_root;
+       char dname[128];
+       int i;
+
+       snprintf(dname, sizeof(dname), "rvic-%d", vcpu->vcpu_id);
+       rvic_root = debugfs_create_dir(dname, vcpu->kvm->debugfs_dentry);
+       if (!rvic_root)
+               return;
+
+       debugfs_create_file("state", 0444, rvic_root, vcpu, &rvic_debug_fops);
+       for (i = 0; i < rvic->nr_total; i++) {
+               snprintf(dname, sizeof(dname), "%d", i);
+               debugfs_create_file(dname, 0444, rvic_root,
+                                   rvic_get_irq(rvic, i),
+                                   &rvic_irq_debug_fops);
+       }
+}
+
+static int rvid_debug_show(struct seq_file *s, void *p)
+{
+       struct kvm *kvm = s->private;
+       struct rvic_vm_data *data = kvm->arch.irqchip_data;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&data->lock, flags);
+
+       seq_printf(s, "%d Trusted\n", data->nr_trusted);
+       seq_printf(s, "%d Total\n", data->nr_total);
+
+       for (i = 0; i < rvic_nr_untrusted(data); i++) {
+               if (data->rvid_map[i].intid < data->nr_trusted)
+                       continue;
+
+               seq_printf(s, "%4u: vcpu-%u %u\n",
+                          i, data->rvid_map[i].target_vcpu,
+                          data->rvid_map[i].intid);
+       }
+
+       spin_unlock_irqrestore(&data->lock, flags);
+
+       return 0;
+}
+
+static int rvid_debug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rvid_debug_show, inode->i_private);
+}
+
+static const struct file_operations rvid_debug_fops = {
+       .open           = rvid_debug_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void rvid_create_debugfs(struct kvm *kvm)
+{
+       debugfs_create_file("rvid", 0444, kvm->debugfs_dentry,
+                           kvm, &rvid_debug_fops);
+}
-- 
2.27.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to