/* * Structure to control looping through the entire vgic state. We start at * zero for each field and move upwards. So, if dist_id is 0 we print the * distributor info. When dist_id is 1, we have already printed it and move * on. * * When vcpu_id < nr_cpus we print the vcpu info until vcpu_id == nr_cpus and * so on.
*/ struct vgic_state_iter { int nr_cpus; int nr_spis; int nr_lpis; int dist_id; int vcpu_id; unsignedlong intid; int lpi_idx;
};
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) &&
iter->nr_lpis) { if (iter->lpi_idx < iter->nr_lpis)
xa_find_after(&dist->lpi_xa, &iter->intid,
VGIC_LPI_MAX_INTID,
LPI_XA_MARK_DEBUG_ITER);
iter->lpi_idx++; return;
}
if (irq->intid < VGIC_NR_SGIS)
type = "SGI"; elseif (irq->intid < VGIC_NR_PRIVATE_IRQS)
type = "PPI"; elseif (irq->intid < VGIC_MAX_SPI)
type = "SPI"; else
type = "LPI";
if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS)
print_header(s, irq, vcpu);
pending = irq->pending_latch; if (irq->hw && vgic_irq_is_sgi(irq->intid)) { int err;
if (iter->vcpu_id < iter->nr_cpus)
vcpu = kvm_get_vcpu(kvm, iter->vcpu_id);
/* * Expect this to succeed, as iter_mark_lpis() takes a reference on * every LPI to be visited.
*/ if (iter->intid < VGIC_NR_PRIVATE_IRQS)
irq = vgic_get_vcpu_irq(vcpu, iter->intid); else
irq = vgic_get_irq(kvm, iter->intid); if (WARN_ON_ONCE(!irq)) return -EINVAL;
/** * struct vgic_its_iter - Iterator for traversing VGIC ITS device tables. * @dev: Pointer to the current its_device being processed. * @ite: Pointer to the current its_ite within the device being processed. * * This structure is used to maintain the current position during iteration * over the ITS device tables. It holds pointers to both the current device * and the current ITE within that device.
*/ struct vgic_its_iter { struct its_device *dev; struct its_ite *ite;
};
/** * end_of_iter - Checks if the iterator has reached the end. * @iter: The iterator to check. * * When the iterator completed processing the final ITE in the last device * table, it was marked to indicate the end of iteration by setting its * device and ITE pointers to NULL. * This function checks whether the iterator was marked as end. * * Return: True if the iterator is marked as end, false otherwise.
*/ staticinlinebool end_of_iter(struct vgic_its_iter *iter)
{ return !iter->dev && !iter->ite;
}
/** * vgic_its_iter_next - Advances the iterator to the next entry in the ITS tables. * @its: The VGIC ITS structure. * @iter: The iterator to advance. * * This function moves the iterator to the next ITE within the current device, * or to the first ITE of the next device if the current ITE is the last in * the device. If the current device is the last device, the iterator is set * to indicate the end of iteration.
*/ staticvoid vgic_its_iter_next(struct vgic_its *its, struct vgic_its_iter *iter)
{ struct its_device *dev = iter->dev; struct its_ite *ite = iter->ite;
if (!ite || list_is_last(&ite->ite_list, &dev->itt_head)) { if (list_is_last(&dev->dev_list, &its->device_list)) {
dev = NULL;
ite = NULL;
} else {
dev = list_next_entry(dev, dev_list);
ite = list_first_entry_or_null(&dev->itt_head, struct its_ite,
ite_list);
}
} else {
ite = list_next_entry(ite, ite_list);
}
iter->dev = dev;
iter->ite = ite;
}
/** * vgic_its_debug_start - Start function for the seq_file interface. * @s: The seq_file structure. * @pos: The starting position (offset). * * This function initializes the iterator to the beginning of the ITS tables * and advances it to the specified position. It acquires the its_lock mutex * to protect shared data. * * Return: An iterator pointer on success, NULL if no devices are found or * the end of the list is reached, or ERR_PTR(-ENOMEM) on memory * allocation failure.
*/ staticvoid *vgic_its_debug_start(struct seq_file *s, loff_t *pos)
{ struct vgic_its *its = s->private; struct vgic_its_iter *iter; struct its_device *dev;
loff_t offset = *pos;
mutex_lock(&its->its_lock);
dev = list_first_entry_or_null(&its->device_list, struct its_device, dev_list); if (!dev) return NULL;
iter = kmalloc(sizeof(*iter), GFP_KERNEL); if (!iter) return ERR_PTR(-ENOMEM);
while (!end_of_iter(iter) && offset--)
vgic_its_iter_next(its, iter);
if (end_of_iter(iter)) {
kfree(iter); return NULL;
}
return iter;
}
/** * vgic_its_debug_next - Next function for the seq_file interface. * @s: The seq_file structure. * @v: The current iterator. * @pos: The current position (offset). * * This function advances the iterator to the next entry and increments the * position. * * Return: An iterator pointer on success, or NULL if the end of the list is * reached.
*/ staticvoid *vgic_its_debug_next(struct seq_file *s, void *v, loff_t *pos)
{ struct vgic_its *its = s->private; struct vgic_its_iter *iter = v;
++*pos;
vgic_its_iter_next(its, iter);
if (end_of_iter(iter)) {
kfree(iter); return NULL;
} return iter;
}
/** * vgic_its_debug_stop - Stop function for the seq_file interface. * @s: The seq_file structure. * @v: The current iterator. * * This function frees the iterator and releases the its_lock mutex.
*/ staticvoid vgic_its_debug_stop(struct seq_file *s, void *v)
{ struct vgic_its *its = s->private; struct vgic_its_iter *iter = v;
if (!IS_ERR_OR_NULL(iter))
kfree(iter);
mutex_unlock(&its->its_lock);
}
/** * vgic_its_debug_show - Show function for the seq_file interface. * @s: The seq_file structure. * @v: The current iterator. * * This function formats and prints the ITS table entry information to the * seq_file output. * * Return: 0 on success.
*/ staticint vgic_its_debug_show(struct seq_file *s, void *v)
{ struct vgic_its_iter *iter = v; struct its_device *dev = iter->dev; struct its_ite *ite = iter->ite;
/** * vgic_its_debug_init - Initializes the debugfs interface for VGIC ITS. * @dev: The KVM device structure. * * This function creates a debugfs file named "vgic-its-state@%its_base" * to expose the ITS table information. * * Return: 0 on success.
*/ int vgic_its_debug_init(struct kvm_device *dev)
{ struct vgic_its *its = dev->private; char *name;
name = kasprintf(GFP_KERNEL, "vgic-its-state@%llx", (u64)its->vgic_its_base); if (!name) return -ENOMEM;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.