From: Shameer Kolothum <skolothumtho@nvidia.com>
To: <kvm@vger.kernel.org>, <linux-pci@vger.kernel.org>,
<linux-kernel@vger.kernel.org>
Cc: <alex@shazbot.org>, <jgg@ziepe.ca>, <kevin.tian@intel.com>,
<kbusch@meta.com>, <michal.winiarski@intel.com>,
<satyanarayana.k.v.p@intel.com>, <sonangp@nvidia.com>,
<nathanc@nvidia.com>, <mochs@nvidia.com>
Subject: [RFC PATCH 16/19] vfio/pci: Quiesce INTx during PCI recovery
Date: Tue, 1 Sep 2026 10:32:14 +0100 [thread overview]
Message-ID: <20260901093217.8539-17-skolothumtho@nvidia.com> (raw)
In-Reply-To: <20260901093217.8539-1-skolothumtho@nvidia.com>
Mask INTx when recovery blocks device access. A PCI 2.3 device shares its
line, so leaving a level interrupt asserted and returning IRQ_NONE would
storm until note_interrupt() disables the line for every device on it.
Mask through pci_check_and_mask_intx() and return IRQ_HANDLED instead. A
device without per-function masking has the line to itself and is quiesced
through genirq.
That is a different job from the masking recovery does for itself, so
vfio_pci_intx_mask_for_recovery() gains a @quiesce argument to tell them
apart. The handler knows an interrupt has fired but not whether this
device is the one asserting the shared line, which is what
pci_check_and_mask_intx() reports, and a false return means the interrupt
belongs to another device. It is also the user who unmasks afterwards,
having been sent the eventfd, so the handler does not record the mask as
one recovery owes.
Record unmask requests received during recovery instead of losing them, so
vfio_pci_intx_recovery_finish() can replay them once the event ends.
The unmask handler checks for a blocked device before the existing INTx
test, so a blocked device is not touched through pci_intx(). It only
dereferences the interrupt context once that test has passed. The DisINTx
emulation calls the unmask path whatever irq_type is set to, and the
context is NULL when INTx is not in use.
Replay from the reset path as well. The unmask eventfd reaches
vfio_pci_intx_unmask_handler() through virqfd, which takes no recovery_lock
and so cannot be refused, and VFIO_DEVICE_RESET blocks access for its
duration. Without a replay there the line stays masked and the guest waits
for an interrupt which cannot arrive, since it only unmasks again after
receiving one.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
drivers/vfio/pci/vfio_pci_core.c | 1 +
drivers/vfio/pci/vfio_pci_intrs.c | 61 ++++++++++++++++++++++++++-----
2 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index b3ad7ed261e1..658cccecab12 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1558,6 +1558,7 @@ int vfio_pci_try_reset_function(struct vfio_pci_core_device *vdev,
VFIO_PCI_RECOVERY_FAILED))) {
vfio_pci_recovery_rom_disable(vdev);
WRITE_ONCE(vdev->pci_recovery_access_blocked, false);
+ vfio_pci_intx_recovery_finish(vdev);
}
up_write(&vdev->recovery_lock);
/*
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index c4a075b5bb2e..1981a64b6e18 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -51,6 +51,15 @@ static bool is_irq_none(struct vfio_pci_core_device *vdev)
vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX);
}
+static bool vfio_pci_recovery_blocks_irq(struct vfio_pci_core_device *vdev)
+{
+ if (!vdev->pci_recovery_supported)
+ return false;
+
+ return READ_ONCE(vdev->pci_recovery_enabled) &&
+ READ_ONCE(vdev->pci_recovery_access_blocked);
+}
+
static
struct vfio_pci_irq_ctx *vfio_irq_ctx_get(struct vfio_pci_core_device *vdev,
unsigned long index)
@@ -173,6 +182,16 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *data)
int ret = 0;
spin_lock_irqsave(&vdev->irqlock, flags);
+ /*
+ * Check for a blocked device before the INTx test below, so a blocked
+ * device is not touched through pci_intx(). @ctx is only valid when
+ * INTx is in use, so record the request only then.
+ */
+ if (unlikely(vfio_pci_recovery_blocks_irq(vdev))) {
+ if (is_intx(vdev))
+ ctx->unmask_pending = true;
+ goto out_unlock;
+ }
/*
* Unmasking comes from ioctl or config, so again, have the
@@ -184,6 +203,9 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *data)
goto out_unlock;
}
+ ctx->unmask_pending = false;
+ ctx->recovery_masked = false;
+
if (ctx->masked && !vdev->virq_disabled) {
/*
* A pending interrupt here would immediately trigger,
@@ -224,13 +246,16 @@ void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
/*
* Mask INTx because recovery has blocked device access. Returns true if this
- * call did the masking, which means recovery is the one which must unmask.
+ * call did the masking.
*
- * Nothing is normally asserted when a recovery starts, and
+ * Set @quiesce when recovery is masking the line itself rather than masking
+ * one delivered interrupt. Nothing is normally asserted at that point, and
* pci_check_and_mask_intx() only writes DisINTx when the status register says
- * an interrupt is pending, so it would leave the line alone. pci_intx() masks
- * whatever the device is doing, as __vfio_pci_intx_mask() already does for the
- * same reason.
+ * an interrupt is pending, so it would leave the line alone. The interrupt
+ * handler wants that test, since a false return there means the interrupt
+ * belongs to another device on a shared line. @quiesce also records that
+ * recovery is the one which must unmask. A masked interrupt which was
+ * delivered is the user's to unmask, exactly as outside recovery.
*
* Masking a pci_2_3 device goes through config space. If the error left
* config space unreadable the write has no effect and the line stays
@@ -239,7 +264,8 @@ void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
* access is blocked.
*/
static bool vfio_pci_intx_mask_for_recovery(struct vfio_pci_core_device *vdev,
- struct vfio_pci_irq_ctx *ctx)
+ struct vfio_pci_irq_ctx *ctx,
+ bool quiesce)
{
lockdep_assert_held(&vdev->irqlock);
@@ -248,11 +274,14 @@ static bool vfio_pci_intx_mask_for_recovery(struct vfio_pci_core_device *vdev,
if (!vdev->pci_2_3)
disable_irq_nosync(vdev->pdev->irq);
- else
+ else if (quiesce)
pci_intx(vdev->pdev, 0);
+ else if (!pci_check_and_mask_intx(vdev->pdev))
+ return false;
ctx->masked = true;
- ctx->recovery_masked = true;
+ if (quiesce)
+ ctx->recovery_masked = true;
return true;
}
@@ -264,6 +293,19 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
int ret = IRQ_NONE;
spin_lock_irqsave(&vdev->irqlock, flags);
+ if (unlikely(vfio_pci_recovery_blocks_irq(vdev))) {
+ /*
+ * Mask rather than return IRQ_NONE with the line still
+ * asserted. For a shared pci_2_3 line an unhandled level
+ * interrupt storms until note_interrupt() disables the line
+ * for every device on it, not just this one.
+ */
+ if (vfio_pci_intx_mask_for_recovery(vdev, ctx, false))
+ ret = IRQ_HANDLED;
+ else if (ctx->masked && !vdev->pci_2_3)
+ ret = IRQ_HANDLED;
+ goto out_unlock;
+ }
if (!vdev->pci_2_3) {
disable_irq_nosync(vdev->pdev->irq);
@@ -275,6 +317,7 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
ret = IRQ_HANDLED;
}
+out_unlock:
spin_unlock_irqrestore(&vdev->irqlock, flags);
if (ret == IRQ_HANDLED)
@@ -298,7 +341,7 @@ void vfio_pci_intx_recovery_start(struct vfio_pci_core_device *vdev)
if (WARN_ON_ONCE(!ctx))
goto out_unlock;
- vfio_pci_intx_mask_for_recovery(vdev, ctx);
+ vfio_pci_intx_mask_for_recovery(vdev, ctx, true);
out_unlock:
spin_unlock_irqrestore(&vdev->irqlock, flags);
--
2.43.0
next prev parent reply other threads:[~2026-09-01 9:34 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 9:31 [RFC PATCH 00/19] vfio/pci: Handle PCI error recovery and report state to userspace Shameer Kolothum
2026-09-01 9:31 ` [RFC PATCH 01/19] vfio/pci: Add PCI error recovery support state Shameer Kolothum
2026-09-01 9:45 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 02/19] vfio/pci: Serialize generic device lifetime with recovery Shameer Kolothum
2026-09-01 9:47 ` sashiko-bot
2026-09-01 13:14 ` K V P, Satyanarayana
2026-09-01 13:37 ` Shameer Kolothum Thodi
2026-09-01 9:32 ` [RFC PATCH 03/19] vfio/pci: Add PCI recovery access guards Shameer Kolothum
2026-09-01 9:39 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 04/19] vfio/pci: Serialize function reset with recovery Shameer Kolothum
2026-09-01 9:45 ` sashiko-bot
2026-09-02 6:06 ` K V P, Satyanarayana
2026-09-03 11:20 ` Shameer Kolothum Thodi
2026-09-01 9:32 ` [RFC PATCH 05/19] vfio/pci: Serialize config access " Shameer Kolothum
2026-09-01 9:46 ` sashiko-bot
2026-09-02 6:27 ` K V P, Satyanarayana
2026-09-03 11:08 ` Shameer Kolothum Thodi
2026-09-01 9:32 ` [RFC PATCH 06/19] vfio/pci: Serialize ioeventfd writes " Shameer Kolothum
2026-09-01 9:43 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 07/19] vfio/pci: Retry BAR faults after temporary recovery Shameer Kolothum
2026-09-01 9:47 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 08/19] vfio/pci: Serialize BAR and ROM access with recovery Shameer Kolothum
2026-09-01 9:48 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 09/19] vfio/pci: Serialize interrupt operations " Shameer Kolothum
2026-09-01 9:42 ` sashiko-bot
2026-09-03 6:34 ` K V P, Satyanarayana
2026-09-03 10:39 ` Shameer Kolothum Thodi
2026-09-01 9:32 ` [RFC PATCH 10/19] vfio/pci: Serialize hot reset " Shameer Kolothum
2026-09-01 9:58 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 11/19] vfio/pci: Serialize runtime PM " Shameer Kolothum
2026-09-01 9:49 ` sashiko-bot
2026-09-03 6:43 ` K V P, Satyanarayana
2026-09-03 10:47 ` Shameer Kolothum Thodi
2026-09-01 9:32 ` [RFC PATCH 12/19] vfio/pci: Serialize physical device information queries " Shameer Kolothum
2026-09-01 9:48 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 13/19] vfio/pci: Serialize DMA-BUF export " Shameer Kolothum
2026-09-01 9:43 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 14/19] vfio/pci: Add generic PCI error slot reset handling Shameer Kolothum
2026-09-01 9:53 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 15/19] vfio/pci: Add INTx helpers for PCI recovery Shameer Kolothum
2026-09-01 9:59 ` sashiko-bot
2026-09-01 9:32 ` Shameer Kolothum [this message]
2026-09-01 9:53 ` [RFC PATCH 16/19] vfio/pci: Quiesce INTx during " sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 17/19] vfio/pci: Add generic PCI error resume handling Shameer Kolothum
2026-09-01 9:55 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 18/19] vfio/pci: Coordinate generic device access with host recovery Shameer Kolothum
2026-09-01 9:56 ` sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 19/19] vfio/pci: Expose and enable host PCI error recovery Shameer Kolothum
2026-09-01 9:56 ` sashiko-bot
2026-09-04 19:09 ` [RFC PATCH 00/19] vfio/pci: Handle PCI error recovery and report state to userspace Alex Williamson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260901093217.8539-17-skolothumtho@nvidia.com \
--to=skolothumtho@nvidia.com \
--cc=alex@shazbot.org \
--cc=jgg@ziepe.ca \
--cc=kbusch@meta.com \
--cc=kevin.tian@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=michal.winiarski@intel.com \
--cc=mochs@nvidia.com \
--cc=nathanc@nvidia.com \
--cc=satyanarayana.k.v.p@intel.com \
--cc=sonangp@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox