On Fri, 10 Jul 2026 14:26:50 -0700 Stanislav Kinsburskii
<[email protected]> wrote:
> MSHV currently faults movable memory regions by taking mmap_read_lock()
> around hmm_range_fault(). That prevents the fault path from handling VMAs
> whose fault handlers need to drop mmap_lock, such as userfaultfd-backed
> mappings.
>
> Use hmm_range_fault_unlocked_timeout() instead. Passing a timeout of 0
> preserves MSHV's existing unbounded retry behavior while letting the HMM
> helper own mmap_lock acquisition and refresh range->notifier_seq internally
> before walking the range. After the fault succeeds, MSHV still takes
> mreg_mutex and checks mmu_interval_read_retry() before installing the pages
> into the region, so the existing invalidation synchronization is preserved.
>
> Fold the small fault-and-lock helper into mshv_region_range_fault(), since
> the remaining retry path is just the standard "fault, take the driver lock,
> check the interval notifier sequence" pattern.
>
> ...
>
> @@ -452,13 +412,19 @@ static int mshv_region_range_fault(struct
> mshv_mem_region *region,
> range.start = region->start_uaddr + page_offset * HV_HYP_PAGE_SIZE;
> range.end = range.start + page_count * HV_HYP_PAGE_SIZE;
>
> - do {
> - ret = mshv_region_hmm_fault_and_lock(region, &range);
> - } while (ret == -EBUSY);
> -
> +again:
> + ret = hmm_range_fault_unlocked_timeout(&range, 0);
> if (ret)
> goto out;
>
> + mutex_lock(®ion->mreg_mutex);
> +
> + if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) {
> + mutex_unlock(®ion->mreg_mutex);
> + cond_resched();
> + goto again;
> + }
> +
If the calling process has realtime scheduling policy and either a)
we're uniprocessor or b) this process and the holder of
interval_sub->invalidate_seq are both pinned to the same CPU then
cond_resched() won't do anything, and this might be an infinite loop?