[PATCH 23/23] KVM: arm64: Add debugfs files for the rVIC/rVID implementation
Marc Zyngier
maz at kernel.org
Thu Sep 3 11:26:10 EDT 2020
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 <maz at 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 <maz at 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
More information about the linux-arm-kernel
mailing list