Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: Use standard seq_file iterator for idregs debugfs

The current implementation uses `idreg_debugfs_iter` in `struct
kvm_arch` to track the sequence position. This effectively makes the
iterator shared across all open file descriptors for the VM.

This approach has significant drawbacks:
- It enforces mutual exclusion, preventing concurrent reads of the
debugfs file (returning -EBUSY).
- It relies on storing transient iterator state in the long-lived VM
structure (`kvm_arch`).
- The use of `u8` for the iterator index imposes an implicit limit of
255 registers. While not currently exceeded, this is fragile against
future architectural growth. Switching to `loff_t` eliminates this
overflow risk.

Refactor the implementation to use the standard `seq_file` iterator.
Instead of storing state in `kvm_arch`, rely on the `pos` argument
passed to the `start` and `next` callbacks, which tracks the logical
index specific to the file descriptor.

This change enables concurrent access and eliminates the
`idreg_debugfs_iter` field from `struct kvm_arch`.

Signed-off-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20260202085721.3954942-2-tabba@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Fuad Tabba and committed by
Marc Zyngier
dcd79ed4 9ace4753

+8 -45
-3
arch/arm64/include/asm/kvm_host.h
··· 373 373 /* Maximum number of counters for the guest */ 374 374 u8 nr_pmu_counters; 375 375 376 - /* Iterator for idreg debugfs */ 377 - u8 idreg_debugfs_iter; 378 - 379 376 /* Hypercall features firmware registers' descriptor */ 380 377 struct kvm_smccc_features smccc_feat; 381 378 struct maple_tree smccc_filter;
+8 -42
arch/arm64/kvm/sys_regs.c
··· 4992 4992 return false; 4993 4993 } 4994 4994 4995 - static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos) 4995 + static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, loff_t pos) 4996 4996 { 4997 4997 unsigned long i, idreg_idx = 0; 4998 4998 ··· 5002 5002 if (!is_vm_ftr_id_reg(reg_to_encoding(r))) 5003 5003 continue; 5004 5004 5005 - if (idreg_idx == pos) 5005 + if (idreg_idx++ == pos) 5006 5006 return r; 5007 - 5008 - idreg_idx++; 5009 5007 } 5010 5008 5011 5009 return NULL; ··· 5012 5014 static void *idregs_debug_start(struct seq_file *s, loff_t *pos) 5013 5015 { 5014 5016 struct kvm *kvm = s->private; 5015 - u8 *iter; 5016 5017 5017 - mutex_lock(&kvm->arch.config_lock); 5018 + if (!test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags)) 5019 + return NULL; 5018 5020 5019 - iter = &kvm->arch.idreg_debugfs_iter; 5020 - if (test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags) && 5021 - *iter == (u8)~0) { 5022 - *iter = *pos; 5023 - if (!idregs_debug_find(kvm, *iter)) 5024 - iter = NULL; 5025 - } else { 5026 - iter = ERR_PTR(-EBUSY); 5027 - } 5028 - 5029 - mutex_unlock(&kvm->arch.config_lock); 5030 - 5031 - return iter; 5021 + return (void *)idregs_debug_find(kvm, *pos); 5032 5022 } 5033 5023 5034 5024 static void *idregs_debug_next(struct seq_file *s, void *v, loff_t *pos) ··· 5025 5039 5026 5040 (*pos)++; 5027 5041 5028 - if (idregs_debug_find(kvm, kvm->arch.idreg_debugfs_iter + 1)) { 5029 - kvm->arch.idreg_debugfs_iter++; 5030 - 5031 - return &kvm->arch.idreg_debugfs_iter; 5032 - } 5033 - 5034 - return NULL; 5042 + return (void *)idregs_debug_find(kvm, *pos); 5035 5043 } 5036 5044 5037 5045 static void idregs_debug_stop(struct seq_file *s, void *v) 5038 5046 { 5039 - struct kvm *kvm = s->private; 5040 - 5041 - if (IS_ERR(v)) 5042 - return; 5043 - 5044 - mutex_lock(&kvm->arch.config_lock); 5045 - 5046 - kvm->arch.idreg_debugfs_iter = ~0; 5047 - 5048 - mutex_unlock(&kvm->arch.config_lock); 5049 5047 } 5050 5048 5051 5049 static int idregs_debug_show(struct seq_file *s, void *v) 5052 5050 { 5053 - const struct sys_reg_desc *desc; 5051 + const struct sys_reg_desc *desc = v; 5054 5052 struct kvm *kvm = s->private; 5055 5053 5056 - desc = idregs_debug_find(kvm, kvm->arch.idreg_debugfs_iter); 5057 - 5058 - if (!desc->name) 5054 + if (!desc) 5059 5055 return 0; 5060 5056 5061 5057 seq_printf(s, "%20s:\t%016llx\n", ··· 5057 5089 5058 5090 void kvm_sys_regs_create_debugfs(struct kvm *kvm) 5059 5091 { 5060 - kvm->arch.idreg_debugfs_iter = ~0; 5061 - 5062 5092 debugfs_create_file("idregs", 0444, kvm->debugfs_dentry, kvm, 5063 5093 &idregs_debug_fops); 5064 5094 }