[PATCH v2 17/36] KVM: arm64: gic: Introduce irq_queue and set_pending_state to irq_ops
Sascha Bischoff
Sascha.Bischoff at arm.com
Fri Dec 19 07:52:41 PST 2025
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 queue_irq_unlock function is made overridable using a new function
pointer in struct irq_ops. In kvm_vgic_inject_irq,
vgic_queue_irq_unlock is overridden if the function pointer is
non-null.
Additionally, a new function is added via a function pointer -
set_pending_state. The intent is for this to be used to directly set
the pending state in hardware.
Both of these new irq_ops are unused in this change - it is purely
providing the infrastructure itself. The subsequent PPI injection
changes provide a demonstration of their usage.
Signed-off-by: Sascha Bischoff <sascha.bischoff at arm.com>
---
arch/arm64/kvm/vgic/vgic.c | 11 +++++++++++
include/kvm/arm_vgic.h | 15 +++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index d88570bb2f9f0..ac8cb0270e1e4 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -404,6 +404,13 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
lockdep_assert_held(&irq->irq_lock);
+ /*
+ * If we have the queue_irq_unlock irq_op, we want to override
+ * the default behaviour. Call that, and return early.
+ */
+ 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) {
@@ -547,7 +554,11 @@ int kvm_vgic_inject_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
else
irq->pending_latch = true;
+ if (irq->ops && irq->ops->set_pending_state)
+ WARN_ON_ONCE(!irq->ops->set_pending_state(vcpu, irq));
+
vgic_queue_irq_unlock(kvm, irq, flags);
+
vgic_put_irq(kvm, irq);
return 0;
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 17cd0295b135f..500709bd62c8d 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -171,6 +171,8 @@ enum vgic_irq_config {
VGIC_CONFIG_LEVEL
};
+struct vgic_irq;
+
/*
* Per-irq ops overriding some common behavious.
*
@@ -189,6 +191,19 @@ struct irq_ops {
* peaking into the physical GIC.
*/
bool (*get_input_level)(int vintid);
+
+ /*
+ * Function pointer to directly set the pending state for interrupts
+ * that don't need to be enqueued on AP lists (for example, GICv5 PPIs).
+ */
+ bool (*set_pending_state)(struct kvm_vcpu *vcpu, struct vgic_irq *irq);
+
+ /*
+ * 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 {
--
2.34.1
More information about the linux-arm-kernel
mailing list