* [PATCH] irqchip/gic-v4: Use a separate lockdep class for vPE doorbell IRQs
@ 2026-10-23 21:52 Colton Lewis
2026-10-23 22:16 ` sashiko-bot
0 siblings, 1 reply; 3+ messages in thread
From: Colton Lewis @ 2026-10-23 21:52 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner
Cc: Radu Rendec, Oliver Upton, linux-arm-kernel, kvmarm, linux-kernel,
Raghavendra Rao Ananta, Colton Lewis
By default, init_desc() assigns the shared irq_desc_lock_class lockdep
key to desc->lock for every struct irq_desc. Device drivers that
register an IRQ affinity notifier establish a lock dependency chain of
&irq_desc_lock_class --> &pool->lock --> &p->pi_lock --> &rq->__lock
when irq_set_affinity_locked() calls schedule_work() while holding
desc->lock.
On GICv4 systems, scheduling out a KVM vCPU calls kvm_sched_out() ->
kvm_arch_vcpu_put() -> vgic_v3_put() -> vgic_v4_put() ->
its_make_vpe_non_resident() -> irq_set_vcpu_affinity() while holding the
scheduler runqueue lock (&rq->__lock). Acquiring the vPE doorbell IRQ's
desc->lock establishes &rq->__lock --> &irq_desc_lock_class, triggering
a lockdep circular locking splat:
WARNING: possible circular locking dependency detected
------------------------------------------------------
VCPU-0/109705 is trying to acquire lock:
ffff0001e41e4cc8 (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0x5c/0xb0
but task is already holding lock:
ffff00dad15fd260 (&rq->__lock){-.-.}-{2:2}, at: __schedule+0x23c/0x1850
which lock already depends on the new lock.
Chain exists of:
&irq_desc_lock_class --> &p->pi_lock --> &rq->__lock
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&rq->__lock);
lock(&p->pi_lock);
lock(&rq->__lock);
lock(&irq_desc_lock_class);
GICv4 vPE doorbell IRQs are internal to KVM and GICv4, set
IRQ_NO_BALANCING, and never register an affinity notifier or queue work
under desc->lock. Assign a dedicated lockdep class to vPE doorbell IRQs
in its_alloc_vcpu_irqs() via irq_set_lockdep_class() to prevent this
false positive.
Fixes: 8e01d9a396e6 ("KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by vcpu_load/put")
Signed-off-by: Colton Lewis <coltonlewis@google.com>
---
Notes:
An LLM-based coding assistant was used to help analyze the lockdep
report and draft this patch. I reviewed the analysis and the change.
Tested with this patch applied to a 6.18-based kernel (the affected
code is identical) on a GICv4.1 host with an idpf NIC and
CONFIG_PROVE_LOCKING=y: bring an idpf interface up, then run the KVM
vgic_lpi_stress selftest pinned to a CPU shared with a busy loop so
the vCPU is preempted while its vPE is resident. Without this patch
the splat fires on the first run. With it, five runs are clean and
lockdep records rq->__lock -> the new vPE doorbell class instead of
irq_desc_lock_class.
drivers/irqchip/irq-gic-v4.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index 8455b4a5fbb0d..68ee288f6a076 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -157,6 +157,8 @@ static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
int its_alloc_vcpu_irqs(struct its_vm *vm)
{
+ static struct lock_class_key vpe_irq_lock_class;
+ static struct lock_class_key vpe_irq_request_class;
int vpe_base_irq, i;
vm->fwnode = irq_domain_alloc_named_id_fwnode("GICv4-vpe",
@@ -183,6 +185,8 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
for (i = 0; i < vm->nr_vpes; i++) {
int ret;
vm->vpes[i]->irq = vpe_base_irq + i;
+ irq_set_lockdep_class(vm->vpes[i]->irq, &vpe_irq_lock_class,
+ &vpe_irq_request_class);
ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
if (ret)
goto err;
--
2.56.0.257.gf7497c7d27-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] irqchip/gic-v4: Use a separate lockdep class for vPE doorbell IRQs
2026-10-23 21:52 [PATCH] irqchip/gic-v4: Use a separate lockdep class for vPE doorbell IRQs Colton Lewis
@ 2026-10-23 22:16 ` sashiko-bot
2026-10-25 10:13 ` Marc Zyngier
0 siblings, 1 reply; 3+ messages in thread
From: sashiko-bot @ 2026-10-23 22:16 UTC (permalink / raw)
To: Colton Lewis; +Cc: kvmarm, Oliver Upton, Marc Zyngier
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] irqchip/gic-v4: missing IRQ_NOTHREAD in its_alloc_vcpu_irqs() causes deadlock
--
commit 3b1ba3145da23221937683b56baa88615a91fb69
Author: Colton Lewis <coltonlewis@google.com>
irqchip/gic-v4: Use a separate lockdep class for vPE doorbell IRQs
This commit assigns a dedicated lockdep class to GICv4 vPE doorbell IRQs in
its_alloc_vcpu_irqs() to avoid a circular locking dependency between
rq->__lock and the shared irq_desc_lock_class when scheduling out a KVM
vCPU.
> diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
> index 8455b4a5fbb0d..68ee288f6a076 100644
> --- a/drivers/irqchip/irq-gic-v4.c
> +++ b/drivers/irqchip/irq-gic-v4.c
> @@ -157,6 +157,8 @@ static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
>
> int its_alloc_vcpu_irqs(struct its_vm *vm)
> {
> + static struct lock_class_key vpe_irq_lock_class;
> + static struct lock_class_key vpe_irq_request_class;
> int vpe_base_irq, i;
>
> vm->fwnode = irq_domain_alloc_named_id_fwnode("GICv4-vpe",
> @@ -183,6 +185,8 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
> for (i = 0; i < vm->nr_vpes; i++) {
> int ret;
> vm->vpes[i]->irq = vpe_base_irq + i;
> + irq_set_lockdep_class(vm->vpes[i]->irq, &vpe_irq_lock_class,
> + &vpe_irq_request_class);
[Severity: High]
Can vpe->irq still establish a vpe_irq_lock_class -> p->pi_lock ->
rq->__lock dependency and deadlock when forced IRQ threading is active (via
the threadirqs boot parameter or CONFIG_PREEMPT_RT=y)?
Neither its_alloc_vcpu_irqs() / its_vpe_irq_domain_alloc() nor DB_IRQ_FLAGS
sets IRQ_NOTHREAD, and vgic_v4_request_vpe_irq() in
arch/arm64/kvm/vgic/vgic-v4.c requests the interrupt without IRQF_NO_THREAD:
int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq)
{
return request_irq(irq, vgic_v4_doorbell_handler, 0, "vcpu", vcpu);
}
Because arm64 unconditionally selects IRQ_FORCED_THREADING, when
force_irqthreads() is enabled, __setup_irq() -> irq_setup_forced_threading()
converts vgic_v4_doorbell_handler into a threaded handler and creates
action->thread for vpe->irq.
While IRQ_NO_BALANCING blocks userspace affinity changes, vgic_v4_load() in
arch/arm64/kvm/vgic/vgic-v4.c directly updates the affinity on vcpu_load():
err = irq_set_affinity(vpe->irq, cpumask_of(smp_processor_id()));
This acquires vpe->irq's desc->lock (vpe_irq_lock_class) and calls
irq_set_affinity_locked() -> irq_try_set_affinity() -> irq_do_set_affinity().
After its_vpe_set_affinity() returns IRQ_SET_MASK_OK_DONE,
irq_do_set_affinity() invokes irq_set_thread_affinity() in
kernel/irq/manage.c while still holding desc->lock:
for_each_action_of_desc(desc, action) {
if (action->thread) {
set_bit(IRQTF_AFFINITY, &action->thread_flags);
wake_up_process(action->thread);
}
Calling wake_up_process() under desc->lock acquires p->pi_lock and
rq->__lock under vpe_irq_lock_class (as does __irq_wake_thread() when the
doorbell interrupt fires). When a resident vCPU is later scheduled out,
__schedule() holds rq->__lock and calls kvm_sched_out() ->
kvm_arch_vcpu_put() -> vgic_v3_put() -> vgic_v4_put() ->
its_make_vpe_non_resident() -> irq_set_vcpu_affinity(), acquiring
vpe_irq_lock_class under rq->__lock.
Should vPE doorbell IRQs also be marked with IRQ_NOTHREAD (or requested with
IRQF_NO_THREAD) so they are never force-threaded?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023215207.1465369-1-coltonlewis@google.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] irqchip/gic-v4: Use a separate lockdep class for vPE doorbell IRQs
2026-10-23 22:16 ` sashiko-bot
@ 2026-10-25 10:13 ` Marc Zyngier
0 siblings, 0 replies; 3+ messages in thread
From: Marc Zyngier @ 2026-10-25 10:13 UTC (permalink / raw)
To: Colton Lewis; +Cc: kvmarm, Oliver Upton, sashiko-reviews
On Fri, 23 Oct 2026 23:16:32 +0100,
sashiko-bot@kernel.org wrote:
>
> Should vPE doorbell IRQs also be marked with IRQ_NOTHREAD (or requested with
> IRQF_NO_THREAD) so they are never force-threaded?
This seems legit. Colton?
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-25 10:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-23 21:52 [PATCH] irqchip/gic-v4: Use a separate lockdep class for vPE doorbell IRQs Colton Lewis
2026-10-23 22:16 ` sashiko-bot
2026-10-25 10:13 ` Marc Zyngier
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.