| From: |
| Stanislav Kinsburskii <skinsburskii-AT-gmail.com> |
| To: |
| Liam.Howlett-AT-oracle.com, akpm-AT-linux-foundation.org, akpm-AT-linux-foundation.org, david-AT-kernel.org, jgg-AT-ziepe.ca, corbet-AT-lwn.net, leon-AT-kernel.org, ljs-AT-kernel.org, mhocko-AT-suse.com, rppt-AT-kernel.org, shuah-AT-kernel.org, skhan-AT-linuxfoundation.org, surenb-AT-google.com, vbabka-AT-kernel.org, skinsburskii-AT-gmail.com, kys-AT-microsoft.com, haiyangz-AT-microsoft.com, wei.liu-AT-kernel.org, decui-AT-microsoft.com, longli-AT-microsoft.com |
| Subject: |
| [PATCH v6 0/4] mm/hmm: Add mmap lock-drop support for userfaultfd-backed mappings |
| Date: |
| Mon, 06 Jul 2026 10:54:52 -0700 |
| Message-ID: |
| <178336023903.504354.7500950448226027718.stgit@skinsburskii> |
| Cc: |
| linux-doc-AT-vger.kernel.org, linux-kernel-AT-vger.kernel.org, linux-kernel-AT-vger.kernel.org, linux-kselftest-AT-vger.kernel.org, linux-mm-AT-kvack.org, linux-hyperv-AT-vger.kernel.org |
| Archive-link: |
| Article |
This series extends the HMM framework to support userfaultfd-backed memory
by allowing the mmap read lock to be dropped during hmm_range_fault().
Some page fault handlers — most notably userfaultfd — require the mmap lock
to be released so that userspace can resolve the fault. The current HMM
interface never sets FAULT_FLAG_ALLOW_RETRY, making it impossible to fault
in pages from userfaultfd-registered regions.
This series follows the established int *locked pattern from
get_user_pages_remote() in mm/gup.c. A new helper function,
hmm_range_fault_locked(), accepts an int *locked parameter. When the
mmap lock is dropped during fault resolution (VM_FAULT_RETRY or
VM_FAULT_COMPLETED), the function returns 0 with *locked = 0, signalling
the caller to restart its walk. The existing hmm_range_fault() is
refactored into a thin wrapper that passes NULL, preserving current
behavior for all existing callers.
Possible approaches to lift this limitation are documented in
Documentation/mm/hmm.rst.
Changes in v6:
- Reworked the new API from the external int *locked pattern to
hmm_range_fault_unlocked(), which owns mmap_read_lock() internally.
- Changed the dropped-lock contract: hmm_range_fault_unlocked() now returns
-EBUSY when the mmap lock is dropped, and callers restart with a fresh
mmu_interval_read_begin() sequence.
- Kept hmm_range_fault() as the locked variant for existing users, preserving
its caller-held mmap lock contract.
- Added an in-tree user by converting the MSHV region fault path to
hmm_range_fault_unlocked().
- Updated Documentation/mm/hmm.rst and kernel-doc to describe the unlocked
helper and retry pattern.
- Updated commit messages to match the new API and return semantics.
- Kept the userfaultfd HMM selftest using the test_hmm unlocked read ioctl
path.
Changes in v5:
- Rework hmm_range_fault_unlockable() retry handling to retry
VM_FAULT_RETRY internally with FAULT_FLAG_TRIED set, matching the
fixup_user_fault() pattern and avoiding repeated first-retry lock drops.
- Distinguish VM_FAULT_RETRY from VM_FAULT_COMPLETED: retry faults now
reacquire the mmap lock internally, while completed faults return to the
caller with *locked = 0 so the caller can restart with a fresh notifier
sequence.
- Document the two *locked return states, including the -EINTR case when a
fatal signal is pending after the mmap lock has already been dropped.
- Update comments around HMM_FAULT_UNLOCKED and the HMM fault loop to match
the current hmm_range_fault_unlockable() implementation.
Changes in v4:
- Rebased on 7.2-rc1
Changes in v3:
- Return -EFAULT from dmirror_fault_unlockable() when the mirrored mm can
no longer be pinned.
- Add an eventfd stop signal for the userfaultfd handler thread to avoid
waiting for the poll timeout on successful test completion.
Changes in v2:
- Split into a preparatory refactor (new patch 1) that moves
handle_mm_fault() out of the walk callbacks, plus a smaller feature
patch on top. Suggested by David Hildenbrand.
- Hugetlb regions are now supported on the unlockable path; the v1
-EFAULT short-circuit and the hugetlb_vma_lock_read drop/retake
dance are gone.
- Distinct internal sentinels for "needs fault" (HMM_FAULT_PENDING)
and "lock dropped" (HMM_FAULT_UNLOCKED).
- Outer loop now re-walks after a successful internal fault so the
faulted pfns end up in range->hmm_pfns.
- Kernel-doc on hmm_range_fault_unlockable() and the
Documentation/mm/hmm.rst example match the implementation.
- Dropped the mshv driver conversion (v1 patch 2); will post
separately.
- Selftest converted to drive the path through test_hmm with a
userfaultfd handler (new HMM_DMIRROR_READ_UNLOCKABLE ioctl).
---
Stanislav Kinsburskii (4):
mm/hmm: move page fault handling out of walk callbacks
mm/hmm: add hmm_range_fault_unlocked() for mmap lock-drop support
selftests/mm: add userfaultfd test for HMM unlocked path
mshv: Use hmm_range_fault_unlocked() for region faults
Documentation/mm/hmm.rst | 59 ++++++++
drivers/hv/mshv_regions.c | 14 +-
include/linux/hmm.h | 1
lib/test_hmm.c | 114 ++++++++++++++++
lib/test_hmm_uapi.h | 1
mm/hmm.c | 223 +++++++++++++++++++++++---------
tools/testing/selftests/mm/hmm-tests.c | 149 +++++++++++++++++++++
7 files changed, 492 insertions(+), 69 deletions(-)