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 15/19] vfio/pci: Add INTx helpers for PCI recovery
Date: Tue, 1 Sep 2026 10:32:13 +0100 [thread overview]
Message-ID: <20260901093217.8539-16-skolothumtho@nvidia.com> (raw)
In-Reply-To: <20260901093217.8539-1-skolothumtho@nvidia.com>
Add the helpers the recovery callbacks need to keep INTx in step with an
error event, and the two per-context flags they record it in. Nothing
calls them yet.
vfio_pci_intx_recovery_start() masks the line when an event begins.
Nothing has fired at that point, and pci_check_and_mask_intx() only writes
DisINTx when the status register says an interrupt is pending, so it would
find nothing to do and leave the line enabled. Use pci_intx() instead,
which masks whatever the device is doing. __vfio_pci_intx_mask() already
does this for the same reason.
vfio_pci_intx_recovery_finish() replays what the event masked, and any
unmask which arrived while it ran, once the event ends. An interrupt which
was masked and delivered while access was blocked is not replayed. The
user was told about it, and unmasks it as it would outside recovery.
vfio_pci_intx_recovery_command() reconciles INTX_DISABLE with the command
word error_detected() saves. error_detected() sets that bit when it writes
the quiesced command word, without recording it as a mask, so the saved
word and ctx->masked can disagree about it. The helper keeps the bit as
the INTx state has it, for resume() to use when it restores the word.
Restoring the saved bit instead would unmask a line the handler still
believes is masked, and a shared pci_2_3 line would storm until
note_interrupt() disabled it for every device on it.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
drivers/vfio/pci/vfio_pci_priv.h | 4 ++
drivers/vfio/pci/vfio_pci_intrs.c | 116 ++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h
index 8a7f9fe22386..5598e472da4b 100644
--- a/drivers/vfio/pci/vfio_pci_priv.h
+++ b/drivers/vfio/pci/vfio_pci_priv.h
@@ -25,6 +25,10 @@ struct vfio_pci_ioeventfd {
bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev);
void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev);
+void vfio_pci_intx_recovery_start(struct vfio_pci_core_device *vdev);
+void vfio_pci_intx_recovery_finish(struct vfio_pci_core_device *vdev);
+u16 vfio_pci_intx_recovery_command(struct vfio_pci_core_device *vdev,
+ u16 command);
int vfio_pci_eventfd_replace_locked(struct vfio_pci_core_device *vdev,
struct vfio_pci_eventfd __rcu **peventfd,
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 64f80f64ff57..c4a075b5bb2e 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -29,6 +29,8 @@ struct vfio_pci_irq_ctx {
struct virqfd *mask;
char *name;
bool masked;
+ bool recovery_masked;
+ bool unmask_pending;
struct irq_bypass_producer producer;
};
@@ -220,6 +222,40 @@ void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
mutex_unlock(&vdev->igate);
}
+/*
+ * 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.
+ *
+ * Nothing is normally asserted when a recovery starts, 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.
+ *
+ * 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
+ * asserted, which is no worse than not trying. For a non-fatal error config
+ * space still works, and this is what keeps a shared line from storming while
+ * access is blocked.
+ */
+static bool vfio_pci_intx_mask_for_recovery(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx)
+{
+ lockdep_assert_held(&vdev->irqlock);
+
+ if (ctx->masked)
+ return false;
+
+ if (!vdev->pci_2_3)
+ disable_irq_nosync(vdev->pdev->irq);
+ else
+ pci_intx(vdev->pdev, 0);
+
+ ctx->masked = true;
+ ctx->recovery_masked = true;
+ return true;
+}
+
static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
{
struct vfio_pci_irq_ctx *ctx = dev_id;
@@ -247,6 +283,86 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
return ret;
}
+void vfio_pci_intx_recovery_start(struct vfio_pci_core_device *vdev)
+{
+ struct vfio_pci_irq_ctx *ctx;
+ unsigned long flags;
+
+ lockdep_assert_held_write(&vdev->recovery_lock);
+
+ spin_lock_irqsave(&vdev->irqlock, flags);
+ if (!is_intx(vdev))
+ goto out_unlock;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ goto out_unlock;
+
+ vfio_pci_intx_mask_for_recovery(vdev, ctx);
+
+out_unlock:
+ spin_unlock_irqrestore(&vdev->irqlock, flags);
+}
+
+/*
+ * Replay the masking recovery did, and any unmask which arrived while it was
+ * blocked. Call this only after access_blocked has been cleared, or the
+ * replayed unmask is swallowed and recorded as pending again with nothing
+ * left to replay it.
+ */
+/*
+ * The command word saved before the quiesce can have INTX_DISABLE clear, but
+ * the INTx handler may have masked the line since. Keep the bit as the INTx
+ * state has it, so hardware and ctx->masked agree until
+ * vfio_pci_intx_recovery_finish() replays. Restoring the saved bit instead
+ * would unmask a line the handler still believes is masked, and a shared
+ * pci_2_3 line would then storm until note_interrupt() disables it.
+ */
+u16 vfio_pci_intx_recovery_command(struct vfio_pci_core_device *vdev,
+ u16 command)
+{
+ struct vfio_pci_irq_ctx *ctx;
+
+ lockdep_assert_held(&vdev->irqlock);
+
+ if (!is_intx(vdev))
+ return command;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (ctx && ctx->masked)
+ command |= PCI_COMMAND_INTX_DISABLE;
+
+ return command;
+}
+
+void vfio_pci_intx_recovery_finish(struct vfio_pci_core_device *vdev)
+{
+ struct vfio_pci_irq_ctx *ctx;
+ unsigned long flags;
+ bool replay = false;
+
+ lockdep_assert_held_write(&vdev->recovery_lock);
+
+ mutex_lock(&vdev->igate);
+ spin_lock_irqsave(&vdev->irqlock, flags);
+ if (!is_intx(vdev))
+ goto out_unlock;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ goto out_unlock;
+
+ replay = ctx->recovery_masked || ctx->unmask_pending;
+ ctx->recovery_masked = false;
+ ctx->unmask_pending = false;
+
+out_unlock:
+ spin_unlock_irqrestore(&vdev->irqlock, flags);
+ if (replay)
+ __vfio_pci_intx_unmask(vdev);
+ mutex_unlock(&vdev->igate);
+}
+
static int vfio_intx_enable(struct vfio_pci_core_device *vdev,
struct eventfd_ctx *trigger)
{
--
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 ` Shameer Kolothum [this message]
2026-09-01 9:59 ` [RFC PATCH 15/19] vfio/pci: Add INTx helpers for PCI recovery sashiko-bot
2026-09-01 9:32 ` [RFC PATCH 16/19] vfio/pci: Quiesce INTx during " Shameer Kolothum
2026-09-01 9:53 ` 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-16-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