History

mshv: Fix level-triggered check on uninitialized data

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.

Stanislav Kinsburskii committed 6 months ago

Commit 0289a671 parent 07622621 file · +14 −11Browse files

Unified · Split

drivers/hv/mshv_eventfd.c+14−11
@@ -473,6 +473,19 @@ static int mshv_irqfd_assign(struct mshv_partition *pt, · 472 unmodified lines
473473 init_poll_funcptr(&irqfd->irqfd_polltbl, mshv_irqfd_queue_proc);
474474
475475 spin_lock_irq(&pt->pt_irqfds_lock);
476+ ret = 0;
477+ hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) {
478+ if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx)
479+ continue;
480+ /* This fd is used for another irq already. */
481+ ret = -EBUSY;
482+ spin_unlock_irq(&pt->pt_irqfds_lock);
483+ goto fail;
484+ }
485+
486+ idx = srcu_read_lock(&pt->pt_irq_srcu);
487+ mshv_irqfd_update(pt, irqfd);
488+
476489 #if IS_ENABLED(CONFIG_X86)
477490 if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE) &&
478491 !irqfd->irqfd_lapic_irq.lapic_control.level_triggered) {
@@ -481,22 +494,12 @@ static int mshv_irqfd_assign(struct mshv_partition *pt, · 2 unmodified lines
481494 * Otherwise return with failure
482495 */
483496 spin_unlock_irq(&pt->pt_irqfds_lock);
497+ srcu_read_unlock(&pt->pt_irq_srcu, idx);
484498 ret = -EINVAL;
485499 goto fail;
486500 }
487501 #endif
488− ret = 0;
489− hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) {
490− if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx)
491− continue;
492− /* This fd is used for another irq already. */
493− ret = -EBUSY;
494− spin_unlock_irq(&pt->pt_irqfds_lock);
495− goto fail;
496− }
497502
498− idx = srcu_read_lock(&pt->pt_irq_srcu);
499− mshv_irqfd_update(pt, irqfd);
500503 hlist_add_head(&irqfd->irqfd_hnode, &pt->pt_irqfds_list);
501504 spin_unlock_irq(&pt->pt_irqfds_lock);
502505

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t