summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSascha Bischoff <Sascha.Bischoff@arm.com>2026-03-19 18:54:39 +0300
committerMarc Zyngier <maz@kernel.org>2026-03-19 21:21:28 +0300
commit4a9a32d3538a9d800067be113b0196271a478c6a (patch)
tree3e30cc90b321933988c7addbc00af9d60e8fba0c
parent8f1fbe2fd279240d6999e3a975d0a51d816e080a (diff)
downloadlinux-4a9a32d3538a9d800067be113b0196271a478c6a.tar.xz
KVM: arm64: gic: Introduce queue_irq_unlock to irq_ops
There are times when the default behaviour of vgic_queue_irq_unlock() is undesirable. This is because some GICs, such a GICv5 which is the main driver for this change, handle the majority of the interrupt lifecycle in hardware. In this case, there is no need for a per-VCPU AP list as the interrupt can be made pending directly. This is done either via the ICH_PPI_x_EL2 registers for PPIs, or with the VDPEND system instruction for SPIs and LPIs. The vgic_queue_irq_unlock() function is made overridable using a new function pointer in struct irq_ops. vgic_queue_irq_unlock() is overridden if the function pointer is non-null. This new irq_op is unused in this change - it is purely providing the infrastructure itself. The subsequent PPI injection changes provide a demonstration of the usage of the queue_irq_unlock irq_op. Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20260319154937.3619520-20-sascha.bischoff@arm.com Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--arch/arm64/kvm/vgic/vgic.c3
-rw-r--r--include/kvm/arm_vgic.h8
2 files changed, 11 insertions, 0 deletions
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 84199d2df80a..c46c0e1db436 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -404,6 +404,9 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
lockdep_assert_held(&irq->irq_lock);
+ if (irq->ops && irq->ops->queue_irq_unlock)
+ return irq->ops->queue_irq_unlock(kvm, irq, flags);
+
retry:
vcpu = vgic_target_oracle(irq);
if (irq->vcpu || !vcpu) {
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index fdad0263499b..e9797c5dbbf0 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -189,6 +189,8 @@ enum vgic_irq_config {
VGIC_CONFIG_LEVEL
};
+struct vgic_irq;
+
/*
* Per-irq ops overriding some common behavious.
*
@@ -207,6 +209,12 @@ struct irq_ops {
* peaking into the physical GIC.
*/
bool (*get_input_level)(int vintid);
+
+ /*
+ * Function pointer to override the queuing of an IRQ.
+ */
+ bool (*queue_irq_unlock)(struct kvm *kvm, struct vgic_irq *irq,
+ unsigned long flags) __releases(&irq->irq_lock);
};
struct vgic_irq {