From 0289a67cd70bf9d3807e289f4efd643e16a6c6b4 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsburskii Date: Thu, 7 May 2026 15:43:43 +0000 Subject: [PATCH] mshv: Fix level-triggered check on uninitialized data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In mshv_irqfd_assign(), the level-triggered validation for resample irqfds checks irqfd_lapic_irq.lapic_control.level_triggered before mshv_irqfd_update() has populated the field. Since the irqfd struct is zero-allocated, level_triggered is always 0 at that point, causing the check to always reject resample irqfds with -EINVAL. This makes level-triggered interrupt resampling — used to avoid interrupt storms with assigned devices — completely non-functional. Move the check after the mshv_irqfd_update() call, which resolves the IRQ routing entry and populates irqfd_lapic_irq with the actual trigger mode. Fixes: 621191d709b14 ("Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs") Signed-off-by: Stanislav Kinsburskii Reviewed-by: Anirudh Rayabharam (Microsoft) Signed-off-by: Wei Liu --- drivers/hv/mshv_eventfd.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/hv/mshv_eventfd.c b/drivers/hv/mshv_eventfd.c index 5995a62aff8d..047e5bd43238 100644 --- a/drivers/hv/mshv_eventfd.c +++ b/drivers/hv/mshv_eventfd.c @@ -473,18 +473,6 @@ static int mshv_irqfd_assign(struct mshv_partition *pt, init_poll_funcptr(&irqfd->irqfd_polltbl, mshv_irqfd_queue_proc); spin_lock_irq(&pt->pt_irqfds_lock); -#if IS_ENABLED(CONFIG_X86) - if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE) && - !irqfd->irqfd_lapic_irq.lapic_control.level_triggered) { - /* - * Resample Fd must be for level triggered interrupt - * Otherwise return with failure - */ - spin_unlock_irq(&pt->pt_irqfds_lock); - ret = -EINVAL; - goto fail; - } -#endif ret = 0; hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) { if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx) @@ -497,6 +485,21 @@ static int mshv_irqfd_assign(struct mshv_partition *pt, idx = srcu_read_lock(&pt->pt_irq_srcu); mshv_irqfd_update(pt, irqfd); + +#if IS_ENABLED(CONFIG_X86) + if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE) && + !irqfd->irqfd_lapic_irq.lapic_control.level_triggered) { + /* + * Resample Fd must be for level triggered interrupt + * Otherwise return with failure + */ + spin_unlock_irq(&pt->pt_irqfds_lock); + srcu_read_unlock(&pt->pt_irq_srcu, idx); + ret = -EINVAL; + goto fail; + } +#endif + hlist_add_head(&irqfd->irqfd_hnode, &pt->pt_irqfds_list); spin_unlock_irq(&pt->pt_irqfds_lock);