[PATCH 20/20] KVM: arm64: Add debugfs file dumping computed RESx values

Fuad Tabba tabba at google.com
Mon Feb 2 00:59:45 PST 2026


Hi Marc,

On Mon, 26 Jan 2026 at 12:17, Marc Zyngier <maz at kernel.org> wrote:
>
> Computing RESx values is hard. Verifying that they are correct is
> harder. Add a debugfs file called "resx" that will dump all the RESx
> values for a given VM.
>
> I found it useful, maybe you will too.

I'm sure I will :)

> Signed-off-by: Marc Zyngier <maz at kernel.org>
> ---
>  arch/arm64/include/asm/kvm_host.h |  1 +
>  arch/arm64/kvm/sys_regs.c         | 98 +++++++++++++++++++++++++++++++
>  2 files changed, 99 insertions(+)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index c82b071ade2a5..54072f6ec9d4b 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -375,6 +375,7 @@ struct kvm_arch {
>
>         /* Iterator for idreg debugfs */
>         u8      idreg_debugfs_iter;
> +       u16     sr_resx_iter;

Storing `sr_resx_iter` in `struct kvm_arch` effectively makes this
debugfs file exclusive (returning -EBUSY on contention). Standard
`seq_file` implementations should be stateless, using the `loff_t
*pos` argument to track the index. This allows multiple users to read
the file simultaneously without blocking each other.

>
>         /* Hypercall features firmware registers' descriptor */
>         struct kvm_smccc_features smccc_feat;
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 88a57ca36d96c..f3f92b489b588 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -5090,12 +5090,110 @@ static const struct seq_operations idregs_debug_sops = {
>
>  DEFINE_SEQ_ATTRIBUTE(idregs_debug);
>
> +static const struct sys_reg_desc *sr_resx_find(struct kvm *kvm, u16 pos)
> +{
> +       unsigned long i, sr_idx = 0;
> +
> +       for (i = 0; i < ARRAY_SIZE(sys_reg_descs); i++) {
> +               const struct sys_reg_desc *r = &sys_reg_descs[i];
> +
> +               if (r->reg < __SANITISED_REG_START__)
> +                       continue;
> +
> +               if (sr_idx == pos)
> +                       return r;
> +
> +               sr_idx++;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void *sr_resx_start(struct seq_file *s, loff_t *pos)
> +{
> +       struct kvm *kvm = s->private;
> +       u16 *iter;
> +
> +       guard(mutex)(&kvm->arch.config_lock);

My understanding of `guard()` is that it releases the lock as soon as
the current scope ends (i.e., when `sr_resx_start() `returns). If the
intention was to protect the iteration, it seems like `sr_resx_next()`
and `sr_resx_show()` would end up running unprotected. That said,
converting this to a standard `seq_file` implementation should remove
the need for locking altogether.

I guess you based your code on the existing code for the idregs
debugfs. I had a look at that, and at vgic-debug, and I think they
both can be simplified and made more robust [1]. I also have a diff
that converts this to use `seq_file`. It's pretty similar to what I
have for idregs in the series I sent out [2]. Let me know if you'd
like me to share it.

Cheers,
/fuad

[1] https://lore.kernel.org/all/20260202085721.3954942-1-tabba@google.com/
[2] https://lore.kernel.org/all/20260202085721.3954942-2-tabba@google.com/




> +
> +       if (!kvm->arch.sysreg_masks)
> +               return NULL;
> +
> +       iter = &kvm->arch.sr_resx_iter;
> +       if (*iter != (u16)~0)
> +               return ERR_PTR(-EBUSY);
> +
> +       *iter = *pos;
> +       if (!sr_resx_find(kvm, *iter))
> +               iter = NULL;
> +
> +       return iter;
> +}
> +
> +static void *sr_resx_next(struct seq_file *s, void *v, loff_t *pos)
> +{
> +       struct kvm *kvm = s->private;
> +
> +       (*pos)++;
> +
> +       if (sr_resx_find(kvm, kvm->arch.sr_resx_iter + 1)) {
> +               kvm->arch.sr_resx_iter++;
> +
> +               return &kvm->arch.sr_resx_iter;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void sr_resx_stop(struct seq_file *s, void *v)
> +{
> +       struct kvm *kvm = s->private;
> +
> +       if (IS_ERR(v))
> +               return;
> +
> +       guard(mutex)(&kvm->arch.config_lock);
> +
> +       kvm->arch.sr_resx_iter = ~0;
> +}
> +
> +static int sr_resx_show(struct seq_file *s, void *v)
> +{
> +       const struct sys_reg_desc *desc;
> +       struct kvm *kvm = s->private;
> +       struct resx resx;
> +
> +       desc = sr_resx_find(kvm, kvm->arch.sr_resx_iter);
> +
> +       if (!desc->name)
> +               return 0;
> +
> +       resx = kvm_get_sysreg_resx(kvm, desc->reg);
> +
> +       seq_printf(s, "%20s:\tRES0:%016llx\tRES1:%016llx\n",
> +                  desc->name, resx.res0, resx.res1);
> +
> +       return 0;
> +}
> +
> +static const struct seq_operations sr_resx_sops = {
> +       .start  = sr_resx_start,
> +       .next   = sr_resx_next,
> +       .stop   = sr_resx_stop,
> +       .show   = sr_resx_show,
> +};
> +
> +DEFINE_SEQ_ATTRIBUTE(sr_resx);
> +
>  void kvm_sys_regs_create_debugfs(struct kvm *kvm)
>  {
>         kvm->arch.idreg_debugfs_iter = ~0;
> +       kvm->arch.sr_resx_iter = ~0;
>
>         debugfs_create_file("idregs", 0444, kvm->debugfs_dentry, kvm,
>                             &idregs_debug_fops);
> +       debugfs_create_file("resx", 0444, kvm->debugfs_dentry, kvm,
> +                           &sr_resx_fops);
>  }
>
>  static void reset_vm_ftr_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *reg)
> --
> 2.47.3
>



More information about the linux-arm-kernel mailing list