* [PATCH v1] vfio/pci: pass FAULT_FLAG_WRITE to vmf_insert_pfn_pmd/pud()
@ 2026-10-24 1:55 Mina Almasry
2026-10-30 21:21 ` Alex Williamson
0 siblings, 1 reply; 2+ messages in thread
From: Mina Almasry @ 2026-10-24 1:55 UTC (permalink / raw)
To: Alex Williamson, Andrew Morton, Peter Xu, kvm, linux-kernel
Cc: Mina Almasry, Kevin Tian, Jason Gunthorpe, stable, Ankit Agrawal,
Ritesh Harjani (IBM)
vfio_pci_vmf_insert_pfn() unconditionally passes write=false to
vmf_insert_pfn_pmd() and vmf_insert_pfn_pud().
In insert_pmd() and insert_pud(), write=false skips marking newly
inserted PMD/PUD entries dirty/young via pmd_mkyoung(pmd_mkdirty()) and
maybe_pmd_mkwrite(). Furthermore, when vma_wants_writenotify() is active
on a shared writable VMA (for example, after CLEAR_REFS_SOFT_DIRTY
clears VM_SOFTDIRTY and calls vma_set_page_prot()), vm_page_prot is
downgraded to read-only so insert_pmd()/insert_pud() with write=false
installs a write-protected huge PMD/PUD. Subsequent write faults enter
wp_huge_pmd() or wp_huge_pud(), which invoke vma->vm_ops->huge_fault()
to upgrade the entry in place. Because vfio_pci_vmf_insert_pfn() passes
write=false, insert_pmd() and insert_pud() see !pmd_none(*pmd) with
!write, do nothing, and return VM_FAULT_NOPAGE without setting the write
bit or splitting the huge page, causing an infinite write page-fault
loop.
Pass vmf->flags & FAULT_FLAG_WRITE to vmf_insert_pfn_pmd() and
vmf_insert_pfn_pud() so write faults properly mark huge PFNMAP entries
dirty and writable.
Fixes: f9e54c3a2f5b ("vfio/pci: implement huge_fault support")
Cc: stable@vger.kernel.org
Cc: Ankit Agrawal <ankita@nvidia.com>
Cc: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Assisted-by: LLM
Signed-off-by: Mina Almasry <almasrymina@google.com>
---
drivers/vfio/pci/vfio_pci_core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index fcbb2da860e2..204d959086e9 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1745,6 +1745,8 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
unsigned long pfn,
unsigned int order)
{
+ bool write = vmf->flags & FAULT_FLAG_WRITE;
+
lockdep_assert_held_read(&vdev->memory_lock);
if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev))
@@ -1754,10 +1756,10 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
if (IS_ENABLED(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) && order == PMD_ORDER)
- return vmf_insert_pfn_pmd(vmf, pfn, false);
+ return vmf_insert_pfn_pmd(vmf, pfn, write);
if (IS_ENABLED(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP) && order == PUD_ORDER)
- return vmf_insert_pfn_pud(vmf, pfn, false);
+ return vmf_insert_pfn_pud(vmf, pfn, write);
return VM_FAULT_FALLBACK;
}
base-commit: 076d7e989cb69f6ded7d60f2a080eb909930061b
--
2.56.0.257.gf7497c7d27-goog
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH v1] vfio/pci: pass FAULT_FLAG_WRITE to vmf_insert_pfn_pmd/pud()
2026-10-24 1:55 [PATCH v1] vfio/pci: pass FAULT_FLAG_WRITE to vmf_insert_pfn_pmd/pud() Mina Almasry
@ 2026-10-30 21:21 ` Alex Williamson
0 siblings, 0 replies; 2+ messages in thread
From: Alex Williamson @ 2026-10-30 21:21 UTC (permalink / raw)
To: Mina Almasry
Cc: Andrew Morton, Peter Xu, kvm, linux-kernel, Kevin Tian,
Jason Gunthorpe, stable, Ankit Agrawal, Ritesh Harjani (IBM),
alex, David Matlack
On Sat, 24 Oct 2026 01:55:40 +0000
Mina Almasry <almasrymina@google.com> wrote:
> vfio_pci_vmf_insert_pfn() unconditionally passes write=false to
> vmf_insert_pfn_pmd() and vmf_insert_pfn_pud().
>
> In insert_pmd() and insert_pud(), write=false skips marking newly
> inserted PMD/PUD entries dirty/young via pmd_mkyoung(pmd_mkdirty()) and
> maybe_pmd_mkwrite(). Furthermore, when vma_wants_writenotify() is active
> on a shared writable VMA (for example, after CLEAR_REFS_SOFT_DIRTY
> clears VM_SOFTDIRTY and calls vma_set_page_prot()), vm_page_prot is
> downgraded to read-only so insert_pmd()/insert_pud() with write=false
> installs a write-protected huge PMD/PUD. Subsequent write faults enter
> wp_huge_pmd() or wp_huge_pud(), which invoke vma->vm_ops->huge_fault()
> to upgrade the entry in place. Because vfio_pci_vmf_insert_pfn() passes
> write=false, insert_pmd() and insert_pud() see !pmd_none(*pmd) with
> !write, do nothing, and return VM_FAULT_NOPAGE without setting the write
> bit or splitting the huge page, causing an infinite write page-fault
> loop.
>
> Pass vmf->flags & FAULT_FLAG_WRITE to vmf_insert_pfn_pmd() and
> vmf_insert_pfn_pud() so write faults properly mark huge PFNMAP entries
> dirty and writable.
This seems correct to me, but the commit log misses the human
practicality portion of the argument, or at least buries it too subtly
for me in the soft-dirty references. AIUI, this is effectively only
reached by something like CRIU twiddling clear_refs via procfs on a
running process. That's the kind of thing someone evaluating this for
stable would want to know.
Given this unique use case, this also looks like a selftest candidate
(Cc +David). Thanks,
Alex
> Fixes: f9e54c3a2f5b ("vfio/pci: implement huge_fault support")
> Cc: stable@vger.kernel.org
> Cc: Ankit Agrawal <ankita@nvidia.com>
> Cc: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
> Assisted-by: LLM
> Signed-off-by: Mina Almasry <almasrymina@google.com>
> ---
> drivers/vfio/pci/vfio_pci_core.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index fcbb2da860e2..204d959086e9 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -1745,6 +1745,8 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
> unsigned long pfn,
> unsigned int order)
> {
> + bool write = vmf->flags & FAULT_FLAG_WRITE;
> +
> lockdep_assert_held_read(&vdev->memory_lock);
>
> if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev))
> @@ -1754,10 +1756,10 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
> return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
>
> if (IS_ENABLED(CONFIG_ARCH_SUPPORTS_PMD_PFNMAP) && order == PMD_ORDER)
> - return vmf_insert_pfn_pmd(vmf, pfn, false);
> + return vmf_insert_pfn_pmd(vmf, pfn, write);
>
> if (IS_ENABLED(CONFIG_ARCH_SUPPORTS_PUD_PFNMAP) && order == PUD_ORDER)
> - return vmf_insert_pfn_pud(vmf, pfn, false);
> + return vmf_insert_pfn_pud(vmf, pfn, write);
>
> return VM_FAULT_FALLBACK;
> }
>
> base-commit: 076d7e989cb69f6ded7d60f2a080eb909930061b
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-30 21:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-24 1:55 [PATCH v1] vfio/pci: pass FAULT_FLAG_WRITE to vmf_insert_pfn_pmd/pud() Mina Almasry
2026-10-30 21:21 ` Alex Williamson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®