All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
To: linux-coco@lists.linux.dev
Cc: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>,
	Ackerley Tng <ackerleytng@google.com>,
	Alex Williamson <alex@shazbot.org>,
	David Woodhouse <dwmw2@infradead.org>,
	David Hildenbrand <david@kernel.org>,
	Jason Gunthorpe <jgg@nvidia.com>,
	"Joerg Roedel (AMD)" <joro@8bytes.org>,
	Kevin Tian <kevin.tian@intel.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Robin Murphy <robin.murphy@arm.com>,
	Sean Christopherson <seanjc@google.com>,
	Alexey Kardashevskiy <aik@amd.com>,
	Xu Yilun <yilun.xu@linux.intel.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Steven Price <steven.price@arm.com>,
	Fred Griffoul <griffoul@gmail.com>,
	iommu@lists.linux.dev, kvm@vger.kernel.org,
	patches@lists.linux.dev
Subject: [RFC PATCH v4 17/25] vfio/pci: Check low-power requests before updating device state
Date: Wed,  4 Nov 2026 20:33:14 +0530	[thread overview]
Message-ID: <20261104150322.3516320-18-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20261104150322.3516320-1-aneesh.kumar@kernel.org>

In vfio_pm_config_write(), check requests for D1, D2 or D3hot before
vfio_default_config_write() updates vconfig. Return -EBUSY if
vfio_pci_bar_state_change_allowed() returns false. D0 requests and
writes to unrelated PMCSR fields retain their existing handling.

Use vfio_pci_begin_bar_state_change() for D3hot transitions in
vfio_lock_and_set_power_state(), and return its error to the config
write caller. On success, retain the existing behavior

In vfio_pci_runtime_pm_entry(), reject explicit low-power entry before
removing BAR mappings or dropping the runtime-PM reference.

These checks currently allow all requests. Later patches reject
low-power requests while the device supplies guest_memfd backing,
because entering a lower power state can make mapped BAR PFNs
inaccessible.

Cc: Alex Williamson <alex@shazbot.org>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: David Hildenbrand <david@kernel.org>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
 drivers/vfio/pci/vfio_pci_config.c | 30 ++++++++++++++++++++++++++----
 drivers/vfio/pci/vfio_pci_core.c   | 30 +++++++++++++++++-------------
 drivers/vfio/pci/vfio_pci_priv.h   |  1 -
 3 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
index 537e7f8bc884..014f865c1eaf 100644
--- a/drivers/vfio/pci/vfio_pci_config.c
+++ b/drivers/vfio/pci/vfio_pci_config.c
@@ -755,11 +755,15 @@ static bool vfio_af_flr_requested(int offset, __le32 val)
  * It takes all the required locks to protect the access of power related
  * variables and then invokes vfio_pci_set_power_state().
  */
-static void vfio_lock_and_set_power_state(struct vfio_pci_core_device *vdev,
+static int vfio_lock_and_set_power_state(struct vfio_pci_core_device *vdev,
 					  pci_power_t state)
 {
+	int ret;
+
 	if (state >= PCI_D3hot) {
-		vfio_pci_zap_and_down_write_memory_lock(vdev);
+		ret = vfio_pci_begin_bar_state_change(vdev);
+		if (ret)
+			return ret;
 		vfio_pci_dma_buf_move(vdev, true);
 	} else {
 		down_write(&vdev->memory_lock);
@@ -768,19 +772,34 @@ static void vfio_lock_and_set_power_state(struct vfio_pci_core_device *vdev,
 	vfio_pci_set_power_state(vdev, state);
 	if (__vfio_pci_memory_enabled(vdev))
 		vfio_pci_dma_buf_move(vdev, false);
-	up_write(&vdev->memory_lock);
+	if (state >= PCI_D3hot)
+		vfio_pci_end_bar_state_change(vdev);
+	else
+		up_write(&vdev->memory_lock);
+	return 0;
+}
+
+static bool vfio_pm_low_power_requested(int offset, __le32 val)
+{
+	return offset == PCI_PM_CTRL &&
+	       (le32_to_cpu(val) & PCI_PM_CTRL_STATE_MASK);
 }
 
 static int vfio_pm_config_write(struct vfio_pci_core_device *vdev, int pos,
 				int count, struct perm_bits *perm,
 				int offset, __le32 val)
 {
+	if (vfio_pm_low_power_requested(offset, val) &&
+	    !vfio_pci_bar_state_change_allowed(vdev))
+		return -EBUSY;
+
 	count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
 	if (count < 0)
 		return count;
 
 	if (offset == PCI_PM_CTRL) {
 		pci_power_t state;
+		int ret;
 
 		switch (le32_to_cpu(val) & PCI_PM_CTRL_STATE_MASK) {
 		case 0:
@@ -797,7 +816,10 @@ static int vfio_pm_config_write(struct vfio_pci_core_device *vdev, int pos,
 			break;
 		}
 
-		vfio_lock_and_set_power_state(vdev, state);
+		ret = vfio_lock_and_set_power_state(vdev, state);
+
+		if (ret)
+			return ret;
 	}
 
 	return count;
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index f31fbd980f3e..6612728a21a4 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -373,24 +373,30 @@ int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t stat
 static int vfio_pci_runtime_pm_entry(struct vfio_pci_core_device *vdev,
 				     struct eventfd_ctx *efdctx)
 {
+	int ret;
+
 	/*
 	 * The vdev power related flags are protected with 'memory_lock'
 	 * semaphore.
 	 */
-	vfio_pci_zap_and_down_write_memory_lock(vdev);
+	ret = vfio_pci_begin_bar_state_change(vdev);
+	if (ret)
+		return ret;
 	vfio_pci_dma_buf_move(vdev, true);
 
 	if (vdev->pm_runtime_engaged) {
-		up_write(&vdev->memory_lock);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_unlock;
 	}
 
-	vdev->pm_runtime_engaged = true;
+	WRITE_ONCE(vdev->pm_runtime_engaged, true);
 	vdev->pm_wake_eventfd_ctx = efdctx;
 	pm_runtime_put_noidle(&vdev->pdev->dev);
-	up_write(&vdev->memory_lock);
+	ret = 0;
 
-	return 0;
+out_unlock:
+	vfio_pci_end_bar_state_change(vdev);
+	return ret;
 }
 
 static int vfio_pci_core_pm_entry(struct vfio_pci_core_device *vdev, u32 flags,
@@ -445,7 +451,11 @@ static int vfio_pci_core_pm_entry_with_wakeup(
 static void __vfio_pci_runtime_pm_exit(struct vfio_pci_core_device *vdev)
 {
 	if (vdev->pm_runtime_engaged) {
-		vdev->pm_runtime_engaged = false;
+		/*
+		 * Guest_memfd provider setup reads this flag with READ_ONCE()
+		 * without memory_lock; runtime resume can clear it concurrently.
+		 */
+		WRITE_ONCE(vdev->pm_runtime_engaged, false);
 		pm_runtime_get_noresume(&vdev->pdev->dev);
 
 		if (vdev->pm_wake_eventfd_ctx) {
@@ -1705,12 +1715,6 @@ static void vfio_pci_zap_bars(struct vfio_pci_core_device *vdev)
 	unmap_mapping_range(core_vdev->inode->i_mapping, start, len, true);
 }
 
-void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device *vdev)
-{
-	down_write(&vdev->memory_lock);
-	vfio_pci_zap_bars(vdev);
-}
-
 int vfio_pci_begin_bar_state_change(struct vfio_pci_core_device *vdev)
 {
 	if (!vfio_pci_bar_state_change_allowed(vdev))
diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h
index 0af93f6d9a8a..f7b3178cc890 100644
--- a/drivers/vfio/pci/vfio_pci_priv.h
+++ b/drivers/vfio/pci/vfio_pci_priv.h
@@ -75,7 +75,6 @@ void vfio_config_free(struct vfio_pci_core_device *vdev);
 int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev,
 			     pci_power_t state);
 
-void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device *vdev);
 /* Success retains memory_lock through the hardware operation. */
 int vfio_pci_begin_bar_state_change(struct vfio_pci_core_device *vdev);
 void vfio_pci_end_bar_state_change(struct vfio_pci_core_device *vdev);
-- 
2.43.0


  parent reply	other threads:[~2026-11-04 15:05 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-04 15:02 [RFC PATCH v4 00/25] KVM/VFIO: Add guest_memfd support for device MMIO Aneesh Kumar K.V (Arm)
2026-11-04 15:02 ` [RFC PATCH v4 01/25] KVM: guest_memfd: Let providers prepare memory regions Aneesh Kumar K.V (Arm)
2026-11-04 15:02 ` [RFC PATCH v4 02/25] KVM: guest_memfd: Dispatch conversion through backing operations Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 03/25] KVM: guest_memfd: Let providers coordinate mapping changes Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 04/25] KVM: guest_memfd: Dispatch revocation through backing operations Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 05/25] KVM: guest_memfd: Split population by backing type Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 06/25] KVM: guest_memfd: Support device-backed PFN providers Aneesh Kumar K.V (Arm)
2026-11-04 18:37   ` Fred Griffoul
2026-11-04 15:03 ` [RFC PATCH v4 07/25] KVM: guest_memfd: Support private/shared conversion of device memory Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 08/25] KVM: guest_memfd: Track private device ranges after attribute updates Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 09/25] KVM: guest_memfd: Support range revocation of device mappings Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 10/25] KVM: guest_memfd: Add shared device mmap through PFN providers Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 11/25] KVM: guest_memfd: Clear private device state on final close Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 12/25] KVM: guest_memfd: Invalidate mappings before memslot unbind Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 13/25] vfio: Track device use by guest_memfd Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 14/25] vfio/pci: Add helpers to check and serialize BAR state changes Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 15/25] vfio/pci: Check command enable changes before updating device state Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 16/25] vfio/pci: Check whether BAR state changes are allowed before reset Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` Aneesh Kumar K.V (Arm) [this message]
2026-11-04 15:03 ` [RFC PATCH v4 18/25] vfio/pci: Track userspace BAR mappings Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 19/25] vfio/pci: Restrict host BAR access for guest_memfd providers Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 20/25] vfio: Dispatch guest_memfd provider operations through the device file Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 21/25] vfio: Serialize guest_memfd attachment with device file operations Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 22/25] vfio/pci: Require D0 before providing guest_memfd BAR backing Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 23/25] iommufd: Support MMIO provider attachment to vDEVICEs Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 24/25] vfio/pci: Add a guest_memfd resource provider for MMIO BARs Aneesh Kumar K.V (Arm)
2026-11-04 15:03 ` [RFC PATCH v4 25/25] KVM: Document device-backed guest_memfd and VFIO usage Aneesh Kumar K.V (Arm)

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=20261104150322.3516320-18-aneesh.kumar@kernel.org \
    --to=aneesh.kumar@kernel.org \
    --cc=ackerleytng@google.com \
    --cc=aik@amd.com \
    --cc=alex@shazbot.org \
    --cc=catalin.marinas@arm.com \
    --cc=david@kernel.org \
    --cc=dwmw2@infradead.org \
    --cc=griffoul@gmail.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-coco@lists.linux.dev \
    --cc=patches@lists.linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=robin.murphy@arm.com \
    --cc=seanjc@google.com \
    --cc=steven.price@arm.com \
    --cc=suzuki.poulose@arm.com \
    --cc=yilun.xu@linux.intel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.