KVM: arm64: Add debugfs file for guest's ID registers
Debugging ID register setup can be a complicated affair. Give the kernel hacker a way to dump that state in an easy to parse way. Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20240214131827.2856277-27-maz@kernel.org Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
parent
b80b701d5a
commit
891766581d
2 changed files with 84 additions and 0 deletions
|
@ -319,6 +319,9 @@ struct kvm_arch {
|
|||
/* PMCR_EL0.N value for the guest */
|
||||
u8 pmcr_n;
|
||||
|
||||
/* Iterator for idreg debugfs */
|
||||
u8 idreg_debugfs_iter;
|
||||
|
||||
/* Hypercall features firmware registers' descriptor */
|
||||
struct kvm_smccc_features smccc_feat;
|
||||
struct maple_tree smccc_filter;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/bitfield.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/cacheinfo.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/printk.h>
|
||||
|
@ -3422,6 +3423,81 @@ static bool emulate_sys_reg(struct kvm_vcpu *vcpu,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void *idregs_debug_start(struct seq_file *s, loff_t *pos)
|
||||
{
|
||||
struct kvm *kvm = s->private;
|
||||
u8 *iter;
|
||||
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
|
||||
iter = &kvm->arch.idreg_debugfs_iter;
|
||||
if (*iter == (u8)~0) {
|
||||
*iter = *pos;
|
||||
if (*iter >= KVM_ARM_ID_REG_NUM)
|
||||
iter = NULL;
|
||||
} else {
|
||||
iter = ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
mutex_unlock(&kvm->arch.config_lock);
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
static void *idregs_debug_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
struct kvm *kvm = s->private;
|
||||
|
||||
(*pos)++;
|
||||
|
||||
if ((kvm->arch.idreg_debugfs_iter + 1) < KVM_ARM_ID_REG_NUM) {
|
||||
kvm->arch.idreg_debugfs_iter++;
|
||||
|
||||
return &kvm->arch.idreg_debugfs_iter;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void idregs_debug_stop(struct seq_file *s, void *v)
|
||||
{
|
||||
struct kvm *kvm = s->private;
|
||||
|
||||
if (IS_ERR(v))
|
||||
return;
|
||||
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
|
||||
kvm->arch.idreg_debugfs_iter = ~0;
|
||||
|
||||
mutex_unlock(&kvm->arch.config_lock);
|
||||
}
|
||||
|
||||
static int idregs_debug_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct kvm *kvm = s->private;
|
||||
const struct sys_reg_desc *desc;
|
||||
|
||||
desc = first_idreg + kvm->arch.idreg_debugfs_iter;
|
||||
|
||||
if (!desc->name)
|
||||
return 0;
|
||||
|
||||
seq_printf(s, "%20s:\t%016llx\n",
|
||||
desc->name, IDREG(kvm, IDX_IDREG(kvm->arch.idreg_debugfs_iter)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations idregs_debug_sops = {
|
||||
.start = idregs_debug_start,
|
||||
.next = idregs_debug_next,
|
||||
.stop = idregs_debug_stop,
|
||||
.show = idregs_debug_show,
|
||||
};
|
||||
|
||||
DEFINE_SEQ_ATTRIBUTE(idregs_debug);
|
||||
|
||||
static void kvm_reset_id_regs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
const struct sys_reg_desc *idreg = first_idreg;
|
||||
|
@ -3441,6 +3517,11 @@ static void kvm_reset_id_regs(struct kvm_vcpu *vcpu)
|
|||
id = reg_to_encoding(idreg);
|
||||
}
|
||||
|
||||
kvm->arch.idreg_debugfs_iter = ~0;
|
||||
|
||||
debugfs_create_file("idregs", 0444, kvm->debugfs_dentry, kvm,
|
||||
&idregs_debug_fops);
|
||||
|
||||
set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue