Commit dcd79ed4 authored by Fuad Tabba's avatar Fuad Tabba Committed by Marc Zyngier
Browse files

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: default avatarFuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20260202085721.3954942-2-tabba@google.com


Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent 9ace4753
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -373,9 +373,6 @@ struct kvm_arch {
	/* Maximum number of counters for the guest */
	u8 nr_pmu_counters;

	/* Iterator for idreg debugfs */
	u8	idreg_debugfs_iter;

	/* Hypercall features firmware registers' descriptor */
	struct kvm_smccc_features smccc_feat;
	struct maple_tree smccc_filter;
+8 −42
Original line number Diff line number Diff line
@@ -4992,7 +4992,7 @@ static bool emulate_sys_reg(struct kvm_vcpu *vcpu,
	return false;
}

static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos)
static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, loff_t pos)
{
	unsigned long i, idreg_idx = 0;

@@ -5002,10 +5002,8 @@ static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos)
		if (!is_vm_ftr_id_reg(reg_to_encoding(r)))
			continue;

		if (idreg_idx == pos)
		if (idreg_idx++ == pos)
			return r;

		idreg_idx++;
	}

	return NULL;
@@ -5014,23 +5012,11 @@ static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos)
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 (test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags) &&
	    *iter == (u8)~0) {
		*iter = *pos;
		if (!idregs_debug_find(kvm, *iter))
			iter = NULL;
	} else {
		iter = ERR_PTR(-EBUSY);
	}

	mutex_unlock(&kvm->arch.config_lock);
	if (!test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags))
		return NULL;

	return iter;
	return (void *)idregs_debug_find(kvm, *pos);
}

static void *idregs_debug_next(struct seq_file *s, void *v, loff_t *pos)
@@ -5039,37 +5025,19 @@ static void *idregs_debug_next(struct seq_file *s, void *v, loff_t *pos)

	(*pos)++;

	if (idregs_debug_find(kvm, kvm->arch.idreg_debugfs_iter + 1)) {
		kvm->arch.idreg_debugfs_iter++;

		return &kvm->arch.idreg_debugfs_iter;
	}

	return NULL;
	return (void *)idregs_debug_find(kvm, *pos);
}

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)
{
	const struct sys_reg_desc *desc;
	const struct sys_reg_desc *desc = v;
	struct kvm *kvm = s->private;

	desc = idregs_debug_find(kvm, kvm->arch.idreg_debugfs_iter);

	if (!desc->name)
	if (!desc)
		return 0;

	seq_printf(s, "%20s:\t%016llx\n",
@@ -5089,8 +5057,6 @@ DEFINE_SEQ_ATTRIBUTE(idregs_debug);

void kvm_sys_regs_create_debugfs(struct kvm *kvm)
{
	kvm->arch.idreg_debugfs_iter = ~0;

	debugfs_create_file("idregs", 0444, kvm->debugfs_dentry, kvm,
			    &idregs_debug_fops);
}