arch/arm64/kvm/vgic/vgic-debug.c

Source file repositories/reference/linux-study-clean/arch/arm64/kvm/vgic/vgic-debug.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kvm/vgic/vgic-debug.c
Extension
.c
Size
12481 bytes
Lines
514
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct vgic_state_iter {
	int nr_cpus;
	int nr_spis;
	int dist_id;
	int vcpu_id;
	unsigned long intid;
};

static void iter_next(struct kvm *kvm, struct vgic_state_iter *iter)
{
	struct vgic_dist *dist = &kvm->arch.vgic;

	if (iter->dist_id == 0) {
		iter->dist_id++;
		return;
	}

	/*
	 * Let the xarray drive the iterator after the last SPI, as the iterator
	 * has exhausted the sequentially-allocated INTID space.
	 */
	if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS - 1)) {
		if (iter->intid == VGIC_LPI_MAX_INTID + 1)
			return;

		rcu_read_lock();
		if (!xa_find_after(&dist->lpi_xa, &iter->intid,
				   VGIC_LPI_MAX_INTID, XA_PRESENT))
			iter->intid = VGIC_LPI_MAX_INTID + 1;
		rcu_read_unlock();
		return;
	}

	iter->intid++;
	if (iter->intid == VGIC_NR_PRIVATE_IRQS &&
	    ++iter->vcpu_id < iter->nr_cpus)
		iter->intid = 0;
}

static int vgic_count_lpis(struct kvm *kvm)
{
	struct vgic_dist *dist = &kvm->arch.vgic;
	struct vgic_irq *irq;
	unsigned long intid;
	int nr_lpis = 0;

	rcu_read_lock();
	xa_for_each(&dist->lpi_xa, intid, irq)
		nr_lpis++;
	rcu_read_unlock();

	return nr_lpis;
}

static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
		      loff_t pos)
{
	int nr_cpus = atomic_read(&kvm->online_vcpus);

	memset(iter, 0, sizeof(*iter));

	iter->nr_cpus = nr_cpus;
	iter->nr_spis = kvm->arch.vgic.nr_spis;

	/* Fast forward to the right position if needed */
	while (pos--)
		iter_next(kvm, iter);
}

static bool end_of_vgic(struct vgic_state_iter *iter)
{
	return iter->dist_id > 0 &&
		iter->vcpu_id == iter->nr_cpus &&
		iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS) &&
		iter->intid > VGIC_LPI_MAX_INTID;
}

static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
{
	struct kvm *kvm = s->private;
	struct vgic_state_iter *iter;

	iter = kmalloc_obj(*iter);
	if (!iter)
		return ERR_PTR(-ENOMEM);

	iter_init(kvm, iter, *pos);

	if (end_of_vgic(iter)) {
		kfree(iter);

Annotation

Implementation Notes