On 12/22/25 10:16, Ankit Soni wrote:
> ======================================================
> WARNING: possible circular locking dependency detected
> 6.19.0-rc2 #20 Tainted: G E
> ------------------------------------------------------
> CPU 58/KVM/28597 is trying to acquire lock:
> ff12c47d4b1f34c0 (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0x58/0xa0
>
> but task is already holding lock:
> ff12c49b28552110 (&svm->ir_list_lock){....}-{2:2}, at: avic_pi_update_irte+0x147/0x270 [kvm_amd]
>
> which lock already depends on the new lock.
>
> Chain exists of:
> &irq_desc_lock_class --> &rq->__lock --> &svm->ir_list_lock
>
> Possible unsafe locking scenario:
>
> CPU0 CPU1
> ---- ----
> lock(&svm->ir_list_lock);
> lock(&rq->__lock);
> lock(&svm->ir_list_lock);
> lock(&irq_desc_lock_class);
>
> *** DEADLOCK ***
>
> So lockdep sees:
>
> &irq_desc_lock_class -> &rq->__lock -> &svm->ir_list_lock
>
> while avic_pi_update_irte() currently holds svm->ir_list_lock and then
> takes irq_desc_lock via irq_set_vcpu_affinity(), which creates the
> potential inversion.
>
> - Is this lockdep warning expected/benign in this code path, or does it
> indicate a real potential deadlock between svm->ir_list_lock and
> irq_desc_lock with AVIC + irq_bypass + VFIO?
I'd treat it as a potential (if unlikely) deadlock:
(a) irq_set_thread_affinity triggers the scheduler via wake_up_process,
while irq_desc->lock is taken
(b) the scheduler calls into KVM with rq_lock taken, and KVM uses
ir_list_lock within __avic_vcpu_load/__avic_vcpu_put
(c) KVM wants to block scheduling for a while and uses ir_list_lock for
that purpose, but then takes irq_set_vcpu_affinity takes irq_desc->lock.
I don't think there's an alternative choice of lock for (c); and there's
no easy way to pull the irq_desc->lock out of the IRQ subsystem--in fact
the stickiness of the situation comes from rq->rq_lock and
irq_desc->lock being both internal and not leaf.
Of the three, the most sketchy is (a); notably, __setup_irq() calls
wake_up_process outside desc->lock. Therefore I'd like so much to treat
it as a kernel/irq/ bug; and the simplest (perhaps too simple...) fix is
to drop the wake_up_process(). The only cost is extra latency on the
next interrupt after an affinity change.
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8b1b4c8a4f54..fc135bd079a4 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -189,14 +189,10 @@ static void irq_set_thread_affinity(struct irq_desc *desc)
struct irqaction *action;
for_each_action_of_desc(desc, action) {
- if (action->thread) {
+ if (action->thread)
set_bit(IRQTF_AFFINITY, &action->thread_flags);
- wake_up_process(action->thread);
- }
- if (action->secondary && action->secondary->thread) {
+ if (action->secondary && action->secondary->thread)
set_bit(IRQTF_AFFINITY, &action->secondary->thread_flags);
- wake_up_process(action->secondary->thread);
- }
}
}
Marc, what do you think?
Paolo
On Mon, Dec 22 2025 at 15:09, Paolo Bonzini wrote:
> On 12/22/25 10:16, Ankit Soni wrote:
>> ======================================================
>> WARNING: possible circular locking dependency detected
>> 6.19.0-rc2 #20 Tainted: G E
>> ------------------------------------------------------
>> CPU 58/KVM/28597 is trying to acquire lock:
>> ff12c47d4b1f34c0 (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0x58/0xa0
>>
>> but task is already holding lock:
>> ff12c49b28552110 (&svm->ir_list_lock){....}-{2:2}, at: avic_pi_update_irte+0x147/0x270 [kvm_amd]
>>
>> which lock already depends on the new lock.
>>
>> Chain exists of:
>> &irq_desc_lock_class --> &rq->__lock --> &svm->ir_list_lock
>>
>> Possible unsafe locking scenario:
>>
>> CPU0 CPU1
>> ---- ----
>> lock(&svm->ir_list_lock);
>> lock(&rq->__lock);
>> lock(&svm->ir_list_lock);
>> lock(&irq_desc_lock_class);
>>
>> *** DEADLOCK ***
>>
>> So lockdep sees:
>>
>> &irq_desc_lock_class -> &rq->__lock -> &svm->ir_list_lock
>>
>> while avic_pi_update_irte() currently holds svm->ir_list_lock and then
>> takes irq_desc_lock via irq_set_vcpu_affinity(), which creates the
>> potential inversion.
>>
>> - Is this lockdep warning expected/benign in this code path, or does it
>> indicate a real potential deadlock between svm->ir_list_lock and
>> irq_desc_lock with AVIC + irq_bypass + VFIO?
>
> I'd treat it as a potential (if unlikely) deadlock:
>
> (a) irq_set_thread_affinity triggers the scheduler via wake_up_process,
> while irq_desc->lock is taken
>
> (b) the scheduler calls into KVM with rq_lock taken, and KVM uses
> ir_list_lock within __avic_vcpu_load/__avic_vcpu_put
>
> (c) KVM wants to block scheduling for a while and uses ir_list_lock for
> that purpose, but then takes irq_set_vcpu_affinity takes irq_desc->lock.
>
> I don't think there's an alternative choice of lock for (c); and there's
> no easy way to pull the irq_desc->lock out of the IRQ subsystem--in fact
Don't even think about that.
> the stickiness of the situation comes from rq->rq_lock and
> irq_desc->lock being both internal and not leaf.
>
> Of the three, the most sketchy is (a); notably, __setup_irq() calls
> wake_up_process outside desc->lock. Therefore I'd like so much to treat
> it as a kernel/irq/ bug; and the simplest (perhaps too simple...) fix is
It's not more sketchy than VIRT assuming that it can do what it wants
under rq->lock. :)
> to drop the wake_up_process(). The only cost is extra latency on the
> next interrupt after an affinity change.
The real problematic cost is that in an isolation scenario the wakeup
happens at the next interrupt which might be far into the isolated
phase. That's why the wakeup is there. See:
c99303a2d2a2 ("genirq: Wake interrupt threads immediately when changing affinity")
Obviously you did not even bother to look that up otherwise you would
have CC'ed Crystal and asked her to take a look...
Thanks,
tglx
On Thu, Jan 08 2026 at 22:28, Thomas Gleixner wrote:
> On Mon, Dec 22 2025 at 15:09, Paolo Bonzini wrote:
>> Of the three, the most sketchy is (a); notably, __setup_irq() calls
>> wake_up_process outside desc->lock. Therefore I'd like so much to treat
>> it as a kernel/irq/ bug; and the simplest (perhaps too simple...) fix is
>
> It's not more sketchy than VIRT assuming that it can do what it wants
> under rq->lock. :)
And just for the record, that's not the only place in the irq core which
has that lock chain.
irq_set_affinity_locked() // invoked with desc::lock held
if (desc->affinity_notify)
schedule_work() // Ends up taking rq::lock
and that's the case since cd7eab44e994 ("genirq: Add IRQ affinity
notifiers"), which was added 15 years ago.
Are you still claiming that this is a kernel/irq bug?
Thanks,
tglx
Sorry, not sure how the previous email ended up encrypted.
On 1/8/26 22:53, Thomas Gleixner wrote:
> On Thu, Jan 08 2026 at 22:28, Thomas Gleixner wrote:
>> On Mon, Dec 22 2025 at 15:09, Paolo Bonzini wrote:
>>> Of the three, the most sketchy is (a); notably, __setup_irq() calls
>>> wake_up_process outside desc->lock. Therefore I'd like so much to treat
>>> it as a kernel/irq/ bug; and the simplest (perhaps too simple...) fix is
>>
>> It's not more sketchy than VIRT assuming that it can do what it wants
>> under rq->lock. 🙂
>
> And just for the record, that's not the only place in the irq core which
> has that lock chain.
>
> irq_set_affinity_locked() // invoked with desc::lock held
> if (desc->affinity_notify)
> schedule_work() // Ends up taking rq::lock
>
> and that's the case since cd7eab44e994 ("genirq: Add IRQ affinity
> notifiers"), which was added 15 years ago.
>
> Are you still claiming that this is a kernel/irq bug?
Not really, I did say I'd like to treat it as a kernel/irq bug...
but certainly didn't have hopes high enough to "claim" that.
I do think that it's ugly to have locks that are internal,
non-leaf and held around callbacks; but people smarter than
me have thought about it and you can't call it a bug anyway.
For x86/AMD we have a way to fix it, so that part is not a problem.
For the call(*) to irq_set_affinity() in arch/arm64/kvm/'s
vgic_v4_load() I think it can be solved as well.
kvm_make_request(KVM_REQ_RELOAD_GICv4) will delay vgic_v4_load()
to a safe spot, so just cache the previous smp_processor_id() and,
if it is different, do the kvm_make_request() and return instead
of calling irq_set_affinity().
vgic_v3_load() is the only place that calls it from the preempt
notifier, so this behavior can be tied to a "bool delay_set_affinity"
argument to vgic_v4_load() or placed in a different function.
Marc/Oliver, does that sound doable?
Paolo
(*) kvm_sched_in() preempt notifier -> kvm_arch_vcpu_load() ->
kvm_vgic_load() -> vgic_v3_load() -> vgic_v4_load()
On Wed, Jan 21 2026 at 19:13, Paolo Bonzini wrote:
> On 1/8/26 22:53, Thomas Gleixner wrote:
>> Are you still claiming that this is a kernel/irq bug?
>
> Not really, I did say I'd like to treat it as a kernel/irq bug...
> but certainly didn't have hopes high enough to "claim" that.
> I do think that it's ugly to have locks that are internal,
> non-leaf and held around callbacks; but people smarter than
> me have thought about it and you can't call it a bug anyway.
Deep core code has a tendency to be ugly. But if it makes your life
easier, then these wakeups can be delayed via an irq_work to be outside
of the lock. That needs some life-time issues to be addressed, but
should be doable.
Thanks,
tglx
On Thu, Jan 22, 2026 at 7:47 PM Thomas Gleixner <tglx@kernel.org> wrote: > > On Wed, Jan 21 2026 at 19:13, Paolo Bonzini wrote: > > On 1/8/26 22:53, Thomas Gleixner wrote: > >> Are you still claiming that this is a kernel/irq bug? > > > > Not really, I did say I'd like to treat it as a kernel/irq bug... > > but certainly didn't have hopes high enough to "claim" that. > > I do think that it's ugly to have locks that are internal, > > non-leaf and held around callbacks; but people smarter than > > me have thought about it and you can't call it a bug anyway. > > Deep core code has a tendency to be ugly. But if it makes your life > easier, then these wakeups can be delayed via an irq_work to be outside > of the lock. That needs some life-time issues to be addressed, but > should be doable. Thanks for the suggestion---hopefully it's not needed at all and we can delay taking the lock in KVM. Paolo
On Wed, 21 Jan 2026 18:13:43 +0000,
Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> Sorry, not sure how the previous email ended up encrypted.
>
> On 1/8/26 22:53, Thomas Gleixner wrote:
> > On Thu, Jan 08 2026 at 22:28, Thomas Gleixner wrote:
> >> On Mon, Dec 22 2025 at 15:09, Paolo Bonzini wrote:
> >>> Of the three, the most sketchy is (a); notably, __setup_irq() calls
> >>> wake_up_process outside desc->lock. Therefore I'd like so much to treat
> >>> it as a kernel/irq/ bug; and the simplest (perhaps too simple...) fix is
> >>
> >> It's not more sketchy than VIRT assuming that it can do what it wants
> >> under rq->lock. 🙂
> >
> > And just for the record, that's not the only place in the irq core which
> > has that lock chain.
> >
> > irq_set_affinity_locked() // invoked with desc::lock held
> > if (desc->affinity_notify)
> > schedule_work() // Ends up taking rq::lock
> >
> > and that's the case since cd7eab44e994 ("genirq: Add IRQ affinity
> > notifiers"), which was added 15 years ago.
> >
> > Are you still claiming that this is a kernel/irq bug?
>
> Not really, I did say I'd like to treat it as a kernel/irq bug...
> but certainly didn't have hopes high enough to "claim" that.
> I do think that it's ugly to have locks that are internal,
> non-leaf and held around callbacks; but people smarter than
> me have thought about it and you can't call it a bug anyway.
>
> For x86/AMD we have a way to fix it, so that part is not a problem.
>
> For the call(*) to irq_set_affinity() in arch/arm64/kvm/'s
> vgic_v4_load() I think it can be solved as well.
> kvm_make_request(KVM_REQ_RELOAD_GICv4) will delay vgic_v4_load()
> to a safe spot, so just cache the previous smp_processor_id() and,
> if it is different, do the kvm_make_request() and return instead
> of calling irq_set_affinity().
>
> vgic_v3_load() is the only place that calls it from the preempt
> notifier, so this behavior can be tied to a "bool delay_set_affinity"
> argument to vgic_v4_load() or placed in a different function.
>
> Marc/Oliver, does that sound doable?
Potentially. But there are a few gotchas that may need surgery beyond
KVM itself, all the way down to the ITS code that abstract the
differences between v4.0 and v4.1.
I'll have a look over the weekend.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
-----BEGIN PGP MESSAGE----- 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 =HPz9 -----END PGP MESSAGE----- -----BEGIN PGP MESSAGE----- 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 =FdiM -----END PGP MESSAGE-----
On Mon, Dec 22, 2025, Paolo Bonzini wrote:
> On 12/22/25 10:16, Ankit Soni wrote:
> > ======================================================
> > WARNING: possible circular locking dependency detected
> > 6.19.0-rc2 #20 Tainted: G E
> > ------------------------------------------------------
> > CPU 58/KVM/28597 is trying to acquire lock:
> > ff12c47d4b1f34c0 (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0x58/0xa0
> >
> > but task is already holding lock:
> > ff12c49b28552110 (&svm->ir_list_lock){....}-{2:2}, at: avic_pi_update_irte+0x147/0x270 [kvm_amd]
> >
> > which lock already depends on the new lock.
> >
> > Chain exists of:
> > &irq_desc_lock_class --> &rq->__lock --> &svm->ir_list_lock
> >
> > Possible unsafe locking scenario:
> >
> > CPU0 CPU1
> > ---- ----
> > lock(&svm->ir_list_lock);
> > lock(&rq->__lock);
> > lock(&svm->ir_list_lock);
> > lock(&irq_desc_lock_class);
> >
> > *** DEADLOCK ***
> >
> > So lockdep sees:
> >
> > &irq_desc_lock_class -> &rq->__lock -> &svm->ir_list_lock
> >
> > while avic_pi_update_irte() currently holds svm->ir_list_lock and then
> > takes irq_desc_lock via irq_set_vcpu_affinity(), which creates the
> > potential inversion.
> >
> > - Is this lockdep warning expected/benign in this code path, or does it
> > indicate a real potential deadlock between svm->ir_list_lock and
> > irq_desc_lock with AVIC + irq_bypass + VFIO?
>
> I'd treat it as a potential (if unlikely) deadlock:
>
> (a) irq_set_thread_affinity triggers the scheduler via wake_up_process,
> while irq_desc->lock is taken
>
> (b) the scheduler calls into KVM with rq_lock taken, and KVM uses
> ir_list_lock within __avic_vcpu_load/__avic_vcpu_put
>
> (c) KVM wants to block scheduling for a while and uses ir_list_lock for
> that purpose, but then takes irq_set_vcpu_affinity takes irq_desc->lock.
>
> I don't think there's an alternative choice of lock for (c); and there's
> no easy way to pull the irq_desc->lock out of the IRQ subsystem--in fact
> the stickiness of the situation comes from rq->rq_lock and
> irq_desc->lock being both internal and not leaf.
>
> Of the three, the most sketchy is (a);
Maybe the most unnecessary, but I think there's a pretty strong argument that
(d) is the most sketchy:
(d) KVM takes svm->ir_list_lock around the call to irq_set_vcpu_affinity()
> notably, __setup_irq() calls wake_up_process outside desc->lock. Therefore
> I'd like so much to treat it as a kernel/irq/ bug; and the simplest (perhaps
> too simple...) fix is to drop the wake_up_process(). The only cost is extra
> latency on the next interrupt after an affinity change.
Alternatively, what if we rework the KVM<=>IOMMU exchange to decouple updating
the IRTE from binding the metadata to the vCPU? KVM already has the necessary
exports to do "out-of-band" updates due to the AVIC architecture requiring IRTE
updates on scheduling changes.
It's a bit wonky (and not yet tested), but I like the idea of making
svm->ir_list_lock a leaf lock so that we don't end up with a game of whack-a-mole,
e.g. if something in the IRQ subsystem changes in the future.
---
arch/x86/include/asm/irq_remapping.h | 3 --
arch/x86/kvm/svm/avic.c | 78 ++++++++++++++++++----------
drivers/iommu/amd/iommu.c | 24 +++------
3 files changed, 57 insertions(+), 48 deletions(-)
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 4e55d1755846..1426ecd09943 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -35,9 +35,6 @@ struct amd_iommu_pi_data {
u64 vapic_addr; /* Physical address of the vCPU's vAPIC. */
u32 ga_tag;
u32 vector; /* Guest vector of the interrupt */
- int cpu;
- bool ga_log_intr;
- bool is_guest_mode;
void *ir_data;
};
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 6b77b2033208..0f4f353c7db6 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -868,6 +868,51 @@ static void svm_ir_list_del(struct kvm_kernel_irqfd *irqfd)
raw_spin_unlock_irqrestore(&to_svm(vcpu)->ir_list_lock, flags);
}
+static int avic_pi_add_irte(struct kvm_kernel_irqfd *irqfd, void *ir_data,
+ struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ int r;
+
+ /*
+ * Prevent the vCPU from being scheduled out or migrated until the IRTE
+ * is updated and its metadata has been added to the list of IRQs being
+ * posted to the vCPU, to ensure the IRTE isn't programmed with stale
+ * pCPU/IsRunning information.
+ */
+ guard(raw_spinlock_irqsave)(&svm->ir_list_lock);
+
+ if (kvm_vcpu_apicv_active(vcpu)) {
+ u64 entry = svm->avic_physical_id_entry;
+ bool ga_log_intr;
+ int cpu;
+
+ /*
+ * Update the target pCPU for IOMMU doorbells if the vCPU is
+ * running. If the vCPU is NOT running, i.e. is blocking or
+ * scheduled out, KVM will update the pCPU info when the vCPU
+ * is awakened and/or scheduled in. See also avic_vcpu_load().
+ */
+ if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {
+ cpu = entry & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
+ ga_log_intr = false;
+ } else {
+ cpu = -1;
+ ga_log_intr = entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR;
+ }
+ r = amd_iommu_activate_guest_mode(ir_data, cpu, ga_log_intr);
+ } else {
+ r = amd_iommu_deactivate_guest_mode(ir_data);
+ }
+
+ if (r)
+ return r;
+
+ irqfd->irq_bypass_data = ir_data;
+ list_add(&irqfd->vcpu_list, &svm->ir_list);
+ return 0;
+}
+
int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
unsigned int host_irq, uint32_t guest_irq,
struct kvm_vcpu *vcpu, u32 vector)
@@ -888,36 +933,11 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
struct amd_iommu_pi_data pi_data = {
.ga_tag = AVIC_GATAG(to_kvm_svm(kvm)->avic_vm_id,
vcpu->vcpu_idx),
- .is_guest_mode = kvm_vcpu_apicv_active(vcpu),
.vapic_addr = avic_get_backing_page_address(to_svm(vcpu)),
.vector = vector,
};
- struct vcpu_svm *svm = to_svm(vcpu);
- u64 entry;
int ret;
- /*
- * Prevent the vCPU from being scheduled out or migrated until
- * the IRTE is updated and its metadata has been added to the
- * list of IRQs being posted to the vCPU, to ensure the IRTE
- * isn't programmed with stale pCPU/IsRunning information.
- */
- guard(raw_spinlock_irqsave)(&svm->ir_list_lock);
-
- /*
- * Update the target pCPU for IOMMU doorbells if the vCPU is
- * running. If the vCPU is NOT running, i.e. is blocking or
- * scheduled out, KVM will update the pCPU info when the vCPU
- * is awakened and/or scheduled in. See also avic_vcpu_load().
- */
- entry = svm->avic_physical_id_entry;
- if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {
- pi_data.cpu = entry & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
- } else {
- pi_data.cpu = -1;
- pi_data.ga_log_intr = entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR;
- }
-
ret = irq_set_vcpu_affinity(host_irq, &pi_data);
if (ret)
return ret;
@@ -932,9 +952,11 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
return -EIO;
}
- irqfd->irq_bypass_data = pi_data.ir_data;
- list_add(&irqfd->vcpu_list, &svm->ir_list);
- return 0;
+ ret = avic_pi_add_irte(irqfd, pi_data.ir_data, vcpu);
+ if (WARN_ON_ONCE(ret))
+ irq_set_vcpu_affinity(host_irq, NULL);
+
+ return ret;
}
return irq_set_vcpu_affinity(host_irq, NULL);
}
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 5d45795c367a..855c6309900c 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -3970,7 +3970,6 @@ EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode);
static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *info)
{
- int ret;
struct amd_iommu_pi_data *pi_data = info;
struct amd_ir_data *ir_data = data->chip_data;
struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
@@ -3993,25 +3992,16 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *info)
ir_data->cfg = irqd_cfg(data);
- if (pi_data) {
- pi_data->ir_data = ir_data;
+ if (!pi_data)
+ return amd_iommu_deactivate_guest_mode(ir_data);
- ir_data->ga_root_ptr = (pi_data->vapic_addr >> 12);
- ir_data->ga_vector = pi_data->vector;
- ir_data->ga_tag = pi_data->ga_tag;
- if (pi_data->is_guest_mode)
- ret = amd_iommu_activate_guest_mode(ir_data, pi_data->cpu,
- pi_data->ga_log_intr);
- else
- ret = amd_iommu_deactivate_guest_mode(ir_data);
- } else {
- ret = amd_iommu_deactivate_guest_mode(ir_data);
- }
-
- return ret;
+ pi_data->ir_data = ir_data;
+ ir_data->ga_root_ptr = (pi_data->vapic_addr >> 12);
+ ir_data->ga_vector = pi_data->vector;
+ ir_data->ga_tag = pi_data->ga_tag;
+ return 0;
}
-
static void amd_ir_update_irte(struct irq_data *irqd, struct amd_iommu *iommu,
struct amd_ir_data *ir_data,
struct irq_2_irte *irte_info,
base-commit: 9448598b22c50c8a5bb77a9103e2d49f134c9578
--
On 12/22/25 20:34, Sean Christopherson wrote:
> On Mon, Dec 22, 2025, Paolo Bonzini wrote:
>> On 12/22/25 10:16, Ankit Soni wrote:
>>> - Is this lockdep warning expected/benign in this code path, or does it
>>> indicate a real potential deadlock between svm->ir_list_lock and
>>> irq_desc_lock with AVIC + irq_bypass + VFIO?
>>
>> I'd treat it as a potential (if unlikely) deadlock:
>>
>> (a) irq_set_thread_affinity triggers the scheduler via wake_up_process,
>> while irq_desc->lock is taken
>>
>> (b) the scheduler calls into KVM with rq_lock taken, and KVM uses
>> ir_list_lock within __avic_vcpu_load/__avic_vcpu_put
>>
>> (c) KVM wants to block scheduling for a while and uses ir_list_lock for
>> that purpose, but then irq_set_vcpu_affinity takes irq_desc->lock.
>>
>> I don't think there's an alternative choice of lock for (c); and there's
>> no easy way to pull the irq_desc->lock out of the IRQ subsystem--in fact
>> the stickiness of the situation comes from rq->rq_lock and
>> irq_desc->lock being both internal and not leaf.
>>
>> Of the three, the most sketchy is (a);
>
> Maybe the most unnecessary, but I think there's a pretty strong argument that
> (d) is the most sketchy:
>
> (d) KVM takes svm->ir_list_lock around the call to irq_set_vcpu_affinity()
That's (c). :)
I called irq_set_thread_affinity() sketchy, because it's a core kernel
subsystem that takes a pretty common lock, and directly calls a function
that takes another very common lock. KVM's deadlock scenario seems like
a relatively natural occurrence, though in this case it can be fixed
outside kernel/irq as well.
>> notably, __setup_irq() calls wake_up_process outside desc->lock. Therefore
>> I'd like so much to treat it as a kernel/irq/ bug; and the simplest (perhaps
>> too simple...) fix is to drop the wake_up_process(). The only cost is extra
>> latency on the next interrupt after an affinity change.
>
> Alternatively, what if we rework the KVM<=>IOMMU exchange to decouple updating
> the IRTE from binding the metadata to the vCPU? KVM already has the necessary
> exports to do "out-of-band" updates due to the AVIC architecture requiring IRTE
> updates on scheduling changes.
In fact this was actually my first idea, exactly because it makes
svm->ir_list_lock a leaf lock!
I threw it away because it makes amd_ir_set_vcpu_affinity() weird,
passing back the ir_data but not really doing anything else. Basically
its role becomes little more than violate abstractions, which seemed
wrong. On the other hand, drivers/iommu is already very much tied to
the KVM vendor modules (in particular avic.c already calls
amd_iommu_{,de}activate_guest_mode), so who am I to judge what the IOMMU
driver does.
Paolo
> It's a bit wonky (and not yet tested), but I like the idea of making
> svm->ir_list_lock a leaf lock so that we don't end up with a game of whack-a-mole,
> e.g. if something in the IRQ subsystem changes in the future.
>
> ---
> arch/x86/include/asm/irq_remapping.h | 3 --
> arch/x86/kvm/svm/avic.c | 78 ++++++++++++++++++----------
> drivers/iommu/amd/iommu.c | 24 +++------
> 3 files changed, 57 insertions(+), 48 deletions(-)
>
> diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
> index 4e55d1755846..1426ecd09943 100644
> --- a/arch/x86/include/asm/irq_remapping.h
> +++ b/arch/x86/include/asm/irq_remapping.h
> @@ -35,9 +35,6 @@ struct amd_iommu_pi_data {
> u64 vapic_addr; /* Physical address of the vCPU's vAPIC. */
> u32 ga_tag;
> u32 vector; /* Guest vector of the interrupt */
> - int cpu;
> - bool ga_log_intr;
> - bool is_guest_mode;
> void *ir_data;
> };
>
> diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> index 6b77b2033208..0f4f353c7db6 100644
> --- a/arch/x86/kvm/svm/avic.c
> +++ b/arch/x86/kvm/svm/avic.c
> @@ -868,6 +868,51 @@ static void svm_ir_list_del(struct kvm_kernel_irqfd *irqfd)
> raw_spin_unlock_irqrestore(&to_svm(vcpu)->ir_list_lock, flags);
> }
>
> +static int avic_pi_add_irte(struct kvm_kernel_irqfd *irqfd, void *ir_data,
> + struct kvm_vcpu *vcpu)
> +{
> + struct vcpu_svm *svm = to_svm(vcpu);
> + int r;
> +
> + /*
> + * Prevent the vCPU from being scheduled out or migrated until the IRTE
> + * is updated and its metadata has been added to the list of IRQs being
> + * posted to the vCPU, to ensure the IRTE isn't programmed with stale
> + * pCPU/IsRunning information.
> + */
> + guard(raw_spinlock_irqsave)(&svm->ir_list_lock);
> +
> + if (kvm_vcpu_apicv_active(vcpu)) {
> + u64 entry = svm->avic_physical_id_entry;
> + bool ga_log_intr;
> + int cpu;
> +
> + /*
> + * Update the target pCPU for IOMMU doorbells if the vCPU is
> + * running. If the vCPU is NOT running, i.e. is blocking or
> + * scheduled out, KVM will update the pCPU info when the vCPU
> + * is awakened and/or scheduled in. See also avic_vcpu_load().
> + */
> + if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {
> + cpu = entry & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
> + ga_log_intr = false;
> + } else {
> + cpu = -1;
> + ga_log_intr = entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR;
> + }
> + r = amd_iommu_activate_guest_mode(ir_data, cpu, ga_log_intr);
> + } else {
> + r = amd_iommu_deactivate_guest_mode(ir_data);
> + }
> +
> + if (r)
> + return r;
> +
> + irqfd->irq_bypass_data = ir_data;
> + list_add(&irqfd->vcpu_list, &svm->ir_list);
> + return 0;
> +}
> +
> int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
> unsigned int host_irq, uint32_t guest_irq,
> struct kvm_vcpu *vcpu, u32 vector)
> @@ -888,36 +933,11 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
> struct amd_iommu_pi_data pi_data = {
> .ga_tag = AVIC_GATAG(to_kvm_svm(kvm)->avic_vm_id,
> vcpu->vcpu_idx),
> - .is_guest_mode = kvm_vcpu_apicv_active(vcpu),
> .vapic_addr = avic_get_backing_page_address(to_svm(vcpu)),
> .vector = vector,
> };
> - struct vcpu_svm *svm = to_svm(vcpu);
> - u64 entry;
> int ret;
>
> - /*
> - * Prevent the vCPU from being scheduled out or migrated until
> - * the IRTE is updated and its metadata has been added to the
> - * list of IRQs being posted to the vCPU, to ensure the IRTE
> - * isn't programmed with stale pCPU/IsRunning information.
> - */
> - guard(raw_spinlock_irqsave)(&svm->ir_list_lock);
> -
> - /*
> - * Update the target pCPU for IOMMU doorbells if the vCPU is
> - * running. If the vCPU is NOT running, i.e. is blocking or
> - * scheduled out, KVM will update the pCPU info when the vCPU
> - * is awakened and/or scheduled in. See also avic_vcpu_load().
> - */
> - entry = svm->avic_physical_id_entry;
> - if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK) {
> - pi_data.cpu = entry & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
> - } else {
> - pi_data.cpu = -1;
> - pi_data.ga_log_intr = entry & AVIC_PHYSICAL_ID_ENTRY_GA_LOG_INTR;
> - }
> -
> ret = irq_set_vcpu_affinity(host_irq, &pi_data);
> if (ret)
> return ret;
> @@ -932,9 +952,11 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
> return -EIO;
> }
>
> - irqfd->irq_bypass_data = pi_data.ir_data;
> - list_add(&irqfd->vcpu_list, &svm->ir_list);
> - return 0;
> + ret = avic_pi_add_irte(irqfd, pi_data.ir_data, vcpu);
> + if (WARN_ON_ONCE(ret))
> + irq_set_vcpu_affinity(host_irq, NULL);
> +
> + return ret;
> }
> return irq_set_vcpu_affinity(host_irq, NULL);
> }
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index 5d45795c367a..855c6309900c 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -3970,7 +3970,6 @@ EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode);
>
> static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *info)
> {
> - int ret;
> struct amd_iommu_pi_data *pi_data = info;
> struct amd_ir_data *ir_data = data->chip_data;
> struct irq_2_irte *irte_info = &ir_data->irq_2_irte;
> @@ -3993,25 +3992,16 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *info)
>
> ir_data->cfg = irqd_cfg(data);
>
> - if (pi_data) {
> - pi_data->ir_data = ir_data;
> + if (!pi_data)
> + return amd_iommu_deactivate_guest_mode(ir_data);
>
> - ir_data->ga_root_ptr = (pi_data->vapic_addr >> 12);
> - ir_data->ga_vector = pi_data->vector;
> - ir_data->ga_tag = pi_data->ga_tag;
> - if (pi_data->is_guest_mode)
> - ret = amd_iommu_activate_guest_mode(ir_data, pi_data->cpu,
> - pi_data->ga_log_intr);
> - else
> - ret = amd_iommu_deactivate_guest_mode(ir_data);
> - } else {
> - ret = amd_iommu_deactivate_guest_mode(ir_data);
> - }
> -
> - return ret;
> + pi_data->ir_data = ir_data;
> + ir_data->ga_root_ptr = (pi_data->vapic_addr >> 12);
> + ir_data->ga_vector = pi_data->vector;
> + ir_data->ga_tag = pi_data->ga_tag;
> + return 0;
> }
>
> -
> static void amd_ir_update_irte(struct irq_data *irqd, struct amd_iommu *iommu,
> struct amd_ir_data *ir_data,
> struct irq_2_irte *irte_info,
>
> base-commit: 9448598b22c50c8a5bb77a9103e2d49f134c9578
> --
>
On Mon, Dec 22, 2025, Paolo Bonzini wrote:
> On 12/22/25 20:34, Sean Christopherson wrote:
> > On Mon, Dec 22, 2025, Paolo Bonzini wrote:
> > > notably, __setup_irq() calls wake_up_process outside desc->lock. Therefore
> > > I'd like so much to treat it as a kernel/irq/ bug; and the simplest (perhaps
> > > too simple...) fix is to drop the wake_up_process(). The only cost is extra
> > > latency on the next interrupt after an affinity change.
> >
> > Alternatively, what if we rework the KVM<=>IOMMU exchange to decouple updating
> > the IRTE from binding the metadata to the vCPU? KVM already has the necessary
> > exports to do "out-of-band" updates due to the AVIC architecture requiring IRTE
> > updates on scheduling changes.
>
> In fact this was actually my first idea, exactly because it makes
> svm->ir_list_lock a leaf lock!
>
> I threw it away because it makes amd_ir_set_vcpu_affinity() weird, passing
> back the ir_data but not really doing anything else. Basically its role
> becomes little more than violate abstractions, which seemed wrong. On the
> other hand, drivers/iommu is already very much tied to the KVM vendor
> modules (in particular avic.c already calls
> amd_iommu_{,de}activate_guest_mode), so who am I to judge what the IOMMU
> driver does.
Yeah, I 100% agree the whole thing is a bit gross, but practically speaking it's
just not feasible to properly abstract the interaction, because in reality the
IOMMU implementation is tightly coupled to the CPU implementation. E.g. passing
in the address of a PID isn't going to work well with an AMD IOMMU, and passing
in the address of a vCPI isn't going to work well with an Intel IOMMU.
And FWIW, the lack of true abstraction isn't limited to x86. ARM's GIGv4 passes
around "struct its_cmd_info" and PPC uses "struct kvmppc_xive_irq_state".
I mean, we could do what GICv4 does and use irq_set_vcpu_affinity() to pass
different commands to the IOMMU, e.g. by formalizing "enum avic_vcpu_action"
between KVM and IOMMU so that avic_update_iommu_vcpu_affinity() wouldn't need to
_directly_ call AMD IOMMU code. But IMO that would be a net negative because in
practice all it would do is make it harder to understand what's going on. And
it would more directly create this potential deadlock.
Huh. Which begs the question of whether or not ARM is also affected by this
deadlock, without the extra hop through svm->ir_list_lock:
(a) irq_set_thread_affinity() triggers the scheduler via wake_up_process(),
while irq_desc->lock is taken
(b) the scheduler calls into KVM with rq_lock taken, and KVM uses
irq_set_vcpu_affinity() via vgic_v4_{load,put}()
If ARM is affected, then maybe fixing this in irq_set_thread_affinity() is indeed
better than fudging around the deadlock in avic.c.
On Mon, Dec 22, 2025 at 03:09:13PM +0100, Paolo Bonzini wrote:
> On 12/22/25 10:16, Ankit Soni wrote:
> > ======================================================
> > WARNING: possible circular locking dependency detected
> > 6.19.0-rc2 #20 Tainted: G E
> > ------------------------------------------------------
> > CPU 58/KVM/28597 is trying to acquire lock:
> > ff12c47d4b1f34c0 (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0x58/0xa0
> >
> > but task is already holding lock:
> > ff12c49b28552110 (&svm->ir_list_lock){....}-{2:2}, at: avic_pi_update_irte+0x147/0x270 [kvm_amd]
> >
> > which lock already depends on the new lock.
> >
> > Chain exists of:
> > &irq_desc_lock_class --> &rq->__lock --> &svm->ir_list_lock
> >
> > Possible unsafe locking scenario:
> >
> > CPU0 CPU1
> > ---- ----
> > lock(&svm->ir_list_lock);
> > lock(&rq->__lock);
> > lock(&svm->ir_list_lock);
> > lock(&irq_desc_lock_class);
> >
> > *** DEADLOCK ***
> >
> > So lockdep sees:
> >
> > &irq_desc_lock_class -> &rq->__lock -> &svm->ir_list_lock
> >
> > while avic_pi_update_irte() currently holds svm->ir_list_lock and then
> > takes irq_desc_lock via irq_set_vcpu_affinity(), which creates the
> > potential inversion.
> >
> > - Is this lockdep warning expected/benign in this code path, or does it
> > indicate a real potential deadlock between svm->ir_list_lock and
> > irq_desc_lock with AVIC + irq_bypass + VFIO?
>
> I'd treat it as a potential (if unlikely) deadlock:
>
> (a) irq_set_thread_affinity triggers the scheduler via wake_up_process,
> while irq_desc->lock is taken
>
> (b) the scheduler calls into KVM with rq_lock taken, and KVM uses
> ir_list_lock within __avic_vcpu_load/__avic_vcpu_put
>
> (c) KVM wants to block scheduling for a while and uses ir_list_lock for
> that purpose, but then takes irq_set_vcpu_affinity takes irq_desc->lock.
>
> I don't think there's an alternative choice of lock for (c); and there's
> no easy way to pull the irq_desc->lock out of the IRQ subsystem--in fact
> the stickiness of the situation comes from rq->rq_lock and
> irq_desc->lock being both internal and not leaf.
>
> Of the three, the most sketchy is (a); notably, __setup_irq() calls
> wake_up_process outside desc->lock. Therefore I'd like so much to treat
> it as a kernel/irq/ bug; and the simplest (perhaps too simple...) fix is
> to drop the wake_up_process(). The only cost is extra latency on the
> next interrupt after an affinity change.
>
> diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
> index 8b1b4c8a4f54..fc135bd079a4 100644
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -189,14 +189,10 @@ static void irq_set_thread_affinity(struct irq_desc *desc)
> struct irqaction *action;
> for_each_action_of_desc(desc, action) {
> - if (action->thread) {
> + if (action->thread)
> set_bit(IRQTF_AFFINITY, &action->thread_flags);
> - wake_up_process(action->thread);
> - }
> - if (action->secondary && action->secondary->thread) {
> + if (action->secondary && action->secondary->thread)
> set_bit(IRQTF_AFFINITY, &action->secondary->thread_flags);
> - wake_up_process(action->secondary->thread);
> - }
> }
> }
> Marc, what do you think?
>
> Paolo
>
Hi Paolo,
With the above patch I’m still seeing the same circular dependency warning.
However, and with Sean’s patch I’m not seeing any warnings.
[ 335.128640] ======================================================
[ 335.128650] WARNING: possible circular locking dependency detected
[ 335.128660] 6.19.0-rc2-dirty #21 Tainted: G E
[ 335.128668] ------------------------------------------------------
[ 335.128675] CPU 96/KVM/28699 is trying to acquire lock:
[ 335.128682] ff453c6b59bb18c0 (&irq_desc_lock_class){-.-.}-{2:2}, at: __irq_get_desc_lock+0x58/0xa0
[ 335.128704]
but task is already holding lock:
[ 335.128712] ff453c8b0946e600 (&svm->ir_list_lock){....}-{2:2}, at: avic_pi_update_irte+0x147/0x270 [kvm_amd]
[ 335.128732]
which lock already depends on the new lock.
[ 335.128742]
the existing dependency chain (in reverse order) is:
[ 335.128751]
-> #4 (&svm->ir_list_lock){....}-{2:2}:
[ 335.128760] _raw_spin_lock_irqsave+0x4e/0xb0
[ 335.128772] __avic_vcpu_put+0x7a/0x150 [kvm_amd]
[ 335.128783] avic_vcpu_put+0x50/0x70 [kvm_amd]
[ 335.128791] svm_vcpu_put+0x38/0x70 [kvm_amd]
[ 335.128800] kvm_arch_vcpu_put+0x21b/0x330 [kvm]
[ 335.128854] kvm_sched_out+0x62/0x90 [kvm]
[ 335.128893] __schedule+0x8d3/0x1d10
[ 335.128901] __cond_resched+0x5c/0x80
[ 335.128909] __kmalloc_cache_noprof+0x3d7/0x730
[ 335.128920] kvm_hv_vcpu_init+0x48/0x260 [kvm]
[ 335.128957] kvm_hv_set_msr_common+0x5b/0x12a0 [kvm]
[ 335.128988] kvm_set_msr_common+0x468/0x1310 [kvm]
[ 335.129019] svm_set_msr+0x645/0x730 [kvm_amd]
[ 335.129028] __kvm_set_msr+0xa3/0x2f0 [kvm]
[ 335.129066] kvm_set_msr_ignored_check+0x23/0x1b0 [kvm]
[ 335.129096] do_set_msr+0x76/0xd0 [kvm]
[ 335.129126] msr_io+0xbe/0x1c0 [kvm]
[ 335.129152] kvm_arch_vcpu_ioctl+0x700/0x2090 [kvm]
[ 335.129181] kvm_vcpu_ioctl+0x632/0xc60 [kvm]
[ 335.129215] __x64_sys_ioctl+0xa5/0x100
[ 335.129224] x64_sys_call+0x1243/0x26b0
[ 335.129234] do_syscall_64+0x93/0x1470
[ 335.129242] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 335.129251]
-> #3 (&rq->__lock){-.-.}-{2:2}:
[ 335.129259] _raw_spin_lock_nested+0x32/0x80
[ 335.129267] raw_spin_rq_lock_nested+0x22/0xa0
[ 335.129276] task_rq_lock+0x5f/0x150
[ 335.129392] cgroup_move_task+0x46/0x110
[ 335.129494] css_set_move_task+0xe1/0x240
[ 335.129614] cgroup_post_fork+0x98/0x2d0
[ 335.129704] copy_process+0x1ea8/0x2330
[ 335.129795] kernel_clone+0xa7/0x440
[ 335.129883] user_mode_thread+0x63/0x90
[ 335.129970] rest_init+0x28/0x200
[ 335.130056] start_kernel+0xae0/0xcd0
[ 335.130144] x86_64_start_reservations+0x18/0x30
[ 335.130230] x86_64_start_kernel+0xfd/0x150
[ 335.130312] common_startup_64+0x13e/0x141
[ 335.130396]
-> #2 (&p->pi_lock){-.-.}-{2:2}:
[ 335.130554] _raw_spin_lock_irqsave+0x4e/0xb0
[ 335.130631] try_to_wake_up+0x59/0xaa0
[ 335.130709] wake_up_process+0x15/0x30
[ 335.130785] create_worker+0x154/0x250
[ 335.130862] workqueue_init+0x414/0x760
[ 335.130938] kernel_init_freeable+0x24f/0x630
[ 335.131013] kernel_init+0x1b/0x200
[ 335.131086] ret_from_fork+0x344/0x3a0
[ 335.131161] ret_from_fork_asm+0x1a/0x30
[ 335.131235]
-> #1 (&pool->lock){-.-.}-{2:2}:
[ 335.131375] _raw_spin_lock+0x34/0x80
[ 335.131448] __queue_work+0xf4/0x740
[ 335.131523] queue_work_on+0x70/0xd0
[ 335.131595] irq_set_affinity_locked+0x13b/0x250
[ 335.131669] __irq_apply_affinity_hint+0xf8/0x120
[ 335.131742] mlx5_irq_alloc+0x28e/0x4e0 [mlx5_core]
[ 335.131884] mlx5_irq_request+0x125/0x140 [mlx5_core]
[ 335.131997] mlx5_irq_request_vector+0xb4/0x110 [mlx5_core]
[ 335.132107] comp_irq_request_pci+0x68/0xf0 [mlx5_core]
[ 335.132219] mlx5_comp_eqn_get+0x127/0x850 [mlx5_core]
[ 335.132327] mlx5e_create_cq+0x58/0x260 [mlx5_core]
[ 335.132452] mlx5e_open_drop_rq+0x11c/0x220 [mlx5_core]
[ 335.132573] mlx5e_init_nic_rx+0x2c/0x270 [mlx5_core]
[ 335.132687] mlx5e_attach_netdev+0xed/0x340 [mlx5_core]
[ 335.132794] _mlx5e_resume+0x6a/0xd0 [mlx5_core]
[ 335.132900] mlx5e_probe+0x5e3/0xa50 [mlx5_core]
[ 335.133010] auxiliary_bus_probe+0x45/0x90
[ 335.133086] really_probe+0xf1/0x410
[ 335.133160] __driver_probe_device+0x8c/0x190
[ 335.133233] driver_probe_device+0x24/0xd0
[ 335.133305] __device_attach_driver+0xcd/0x170
[ 335.133377] bus_for_each_drv+0x99/0x100
[ 335.133450] __device_attach+0xba/0x1f0
[ 335.133523] device_initial_probe+0x4e/0x50
[ 335.133595] bus_probe_device+0x3c/0xa0
[ 335.133668] device_add+0x6af/0x8a0
[ 335.133740] __auxiliary_device_add+0x43/0xc0
[ 335.133813] add_adev+0xd3/0x160 [mlx5_core]
[ 335.133931] mlx5_rescan_drivers_locked+0x1ee/0x340 [mlx5_core]
[ 335.134045] mlx5_register_device+0x37/0xb0 [mlx5_core]
[ 335.134156] mlx5_init_one_devl_locked+0x43e/0x710 [mlx5_core]
[ 335.134267] probe_one+0x35b/0x530 [mlx5_core]
[ 335.134382] local_pci_probe+0x47/0xb0
[ 335.134460] work_for_cpu_fn+0x1a/0x30
[ 335.134538] process_one_work+0x22b/0x6f0
[ 335.134613] worker_thread+0x1c6/0x3b0
[ 335.134687] kthread+0x110/0x230
[ 335.134764] ret_from_fork+0x344/0x3a0
[ 335.134838] ret_from_fork_asm+0x1a/0x30
[ 335.134913]
-> #0 (&irq_desc_lock_class){-.-.}-{2:2}:
[ 335.135059] __lock_acquire+0x1595/0x2640
[ 335.135135] lock_acquire+0xc4/0x2c0
[ 335.135210] _raw_spin_lock_irqsave+0x4e/0xb0
[ 335.135286] __irq_get_desc_lock+0x58/0xa0
[ 335.135362] irq_set_vcpu_affinity+0x4a/0x100
[ 335.135438] avic_pi_update_irte+0x170/0x270 [kvm_amd]
[ 335.135521] kvm_pi_update_irte+0xea/0x220 [kvm]
[ 335.135633] kvm_arch_irq_bypass_add_producer+0x9b/0xb0 [kvm]
[ 335.135737] __connect+0x5f/0x100 [irqbypass]
[ 335.135815] irq_bypass_register_producer+0xe4/0xb90 [irqbypass]
[ 335.135895] vfio_msi_set_vector_signal+0x1b0/0x330 [vfio_pci_core]
[ 335.135979] vfio_msi_set_block+0x5a/0xd0 [vfio_pci_core]
[ 335.136060] vfio_pci_set_msi_trigger+0x19e/0x260 [vfio_pci_core]
[ 335.136142] vfio_pci_set_irqs_ioctl+0x46/0x140 [vfio_pci_core]
[ 335.136224] vfio_pci_core_ioctl+0x6ea/0xc20 [vfio_pci_core]
[ 335.136306] vfio_device_fops_unl_ioctl+0xb1/0x9d0 [vfio]
[ 335.136390] __x64_sys_ioctl+0xa5/0x100
[ 335.136470] x64_sys_call+0x1243/0x26b0
[ 335.136553] do_syscall_64+0x93/0x1470
[ 335.136632] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 335.136712]
other info that might help us debug this:
[ 335.136942] Chain exists of:
&irq_desc_lock_class --> &rq->__lock --> &svm->ir_list_lock
[ 335.137178] Possible unsafe locking scenario:
[ 335.137340] CPU0 CPU1
[ 335.137420] ---- ----
[ 335.137502] lock(&svm->ir_list_lock);
[ 335.137582] lock(&rq->__lock);
[ 335.137664] lock(&svm->ir_list_lock);
[ 335.137746] lock(&irq_desc_lock_class);
[ 335.137826]
*** DEADLOCK ***
[ 335.138057] 4 locks held by CPU 96/KVM/28699:
[ 335.138136] #0: ff453c6c28bae800 (&vdev->igate){+.+.}-{4:4}, at: vfio_pci_core_ioctl+0x6d2/0xc20 [vfio_pci_core]
[ 335.138223] #1: ffffffffc0faf110 (lock#10){+.+.}-{4:4}, at: irq_bypass_register_producer+0x31/0xb90 [irqbypass]
[ 335.138310] #2: ff453c8b11179478 (&kvm->irqfds.lock){....}-{3:3}, at: kvm_arch_irq_bypass_add_producer+0x2d/0xb0 [kvm]
[ 335.138423] #3: ff453c8b0946e600 (&svm->ir_list_lock){....}-{2:2}, at: avic_pi_update_irte+0x147/0x270 [kvm_amd]
-Ankit
© 2016 - 2026 Red Hat, Inc.