From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.128.47 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794569294; b=IXg+cO/kguEge884DmyvXl/zC3/n4+Ms/q78jIaUJRxEyFGr6do8CVKNPOWoVleq6JCj acEbFHoQ2cekE3jzcuXVt8ln+FLmryFQdBgdxv3kHDc3/lz95XMO+DAXjM3ctv69mAirb n4XIk/sZRWlOu4z2O5v1zagZxL1NSio5xhQDKA666WFrb2HGubAghHl7oi7OyfEufkKxF FAYiv7lSsgWVZjE7ni5vCodgcP4chUn4E4SV9mpaKHKA223GzT3zp+PySYoXk4+rh0ryQ Fbp6+jAs7jn4fwBNYBHhank9S/yHQN7NprdUgYg0tIxfUZfR9QhHvHP23ID08sgefqw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794569294; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received:Received: From:To:Cc:Subject:Date:Message-ID:X-Mailer:MIME-Version:Content-Type: Content-Transfer-Encoding; bh=/0hFdLUUBMubQi9ZZLh74tQ0C+rY0zzfWhh+F7mlSYU=; b=zuvTNDOOE5KE7b+2PJLv5JqBMBAbI/AGHN6JUPwCX/j3bIZJ0p//Tpr1bs8X7E6ff7Fw 7Vl/Y/qHhTJUSUG8ED6ghdfWEnU+4xsZpUXItsprOqM33WcUnBniMcm3G74cg4gQ+6/mK 6Im9sVmIqfqE1Eegu6Dt1pAHZa6wYfRdiKbfUmPIghkaNTpsx8NC3gurhDzuTtF1n2GBj Wa7snYrrr+rGJ1gHB9vsLMjf13jttSi796OJflNDN1VvTRc1xG7V7c9VaYZ2C3ONdL2mN X1iuSwi0eiDiKfCgcPKvK067F/9ZuYLgIULveEFuy75q5297/62C3w/imO73PkDk1bA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20260707 header.b="Nb9Vr/jI"; arc=none smtp.remote-ip=209.85.128.47 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 96299606A321 for ; Fri, 13 Nov 2026 11:28:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 96299606A321 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20260707 header.b=Nb9Vr/jI Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-4a59100fa83so5641895e9.0 for ; Fri, 13 Nov 2026 03:28:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794569292; x=1795174092; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=/0hFdLUUBMubQi9ZZLh74tQ0C+rY0zzfWhh+F7mlSYU=; b=Nb9Vr/jI7+IuNc/+SwtDXA4rDxVd/FSO1D8SAuF3dNjS98p9gcQX29pKO9uA/isGTz oiWzIoZ+uLHtD/9s0flk2+s4YKkf2NfblXxSY2ZketonWfN7fNgUUeCA4A24mc8JW66j NSsqExUqDIZ4qQ10a1bZtAUMToInJUaWSZzCcpBF6lf6rQNUTxNdem0sDjLZlCLKomDY kGU76SxdTVCCONEMEwKLgqUDHqQkzvpE4pKuJzdHVGDQ+BlD983r+89sVTO/ilCvlQ8j 4HAP2yNhQ5gpK7sy+kV5hc0Xd/1NT8HZdM247Zzra9gmzb4Ybaj907HYRG/UymSRYdGd rpKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794569292; x=1795174092; h=content-transfer-encoding:content-type:mime-version:message-id:date :subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=/0hFdLUUBMubQi9ZZLh74tQ0C+rY0zzfWhh+F7mlSYU=; b=y/Gqz2V7ruissBgITkJarx2mYaw3fuT5O8pDGEtFoy8fi2bKC9UzhHAg8MUOwPOIut enzrs6kiPZiGEdQXHCP2rcG9/UgrmzEum00wFMzWORJbgXg4yQj8uggXVehadOcJlXDI PDqbYbBdSKvm6e3ylzzPoJ8G1POrk+SGjv/xdCxRb4iBvBRrW+dYxamYXdCyS8K0xH2O v2XNFwsc24Tg0RjRlixR4hWtHWt/3KWtSeOHJjsG2dLLbumvI2tY7osA3uoiq0QBI30z pUjO5PQeUmhys/NPQQc1cAESsjQRukrjYtg6zUrEoVZOnk1uVa+GPjUk7ishnSdZ0nS3 6V8w== X-Forwarded-Encrypted: i=1; AL+hErEOcUkIRbxGltahcndg5JN64yAqOmtXIYl/DetHQhhV1w9s0hdF/oRgk+v7OeBEys/pp7fMdE0WxiY=@vger.kernel.org X-Gm-Message-State: APuU4Z/RrLH7dAiuzh4xwBDpevRDuYmcXmhfkBFuwmDvfHGYQlVNcGTM mFER73MXM7PfbhIEjeSKjIjznnFhIZxkJlPjPPJqCJvpG+6AuldY8+SQ X-Gm-Gg: AYBFou23Q8qS8oJJLtHxcLi9yU12Lwgi6kjy8sUjc5VN33rvH8CkQDbcbIKTgPJWGjZ vSwKf4gH353yl849kqhLcA18j5xjVpJ4f+KcbFaUwOv34nmdJruHkjXXiEkgYwW7fR32cY0hDRR 8zC5HdemV7BqCS0emJPaVxlDsp2tILt4xiXDwLDSYEhsxcwbHjpbcpYrmFfCaayjOH78B3vEdka +ZWKcR+/LHcNWxWYzvT5G8q2b7mIeuCWTqbaM7SUZvJioIjtul8Szf55bqLmZaB/QMdkOH1yzrM rW5Pw3yvpBHjcQK9Jq6fIYwNIR5DZh9iVeVZ96fUxee1v64vMCkBCsZAMwC1KJAukiZfI6yJp+k 87EJFGK7o+2h1OZrqeP129pQR2Y+xtfPWQ1cqJBcELOKMWUlNkqv3lh73jukb/A+IVr8naw4f1U obbRt6SSTi3y/goLdhxaBTGwE/6nK2wTjmSSVJh2X1rSyRrIhN7dPv/QNKb5yU4iB5koBiXaniS ddO7qUVAEbnt650hfdSS5hTHAP/rLPYzMbo0LjlRs5IA+XgsvWENVShQrqZAelIdxNzct9AQ0wt lcPAVg5ECXiHLA== X-Received: by 2002:a05:600c:3e17:b0:4bb:53e4:a7c8 with SMTP id 5b1f17b1804b1-4bb55aa27cfmr44169585e9.22.1794569291720; Fri, 13 Nov 2026 03:28:11 -0800 (PST) Received: from nobara ([83.231.69.9]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4bb56680ea9sm35107545e9.0.2026.11.13.03.28.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2026 03:28:11 -0800 (PST) From: "Jose A. Perez de Azpillaga" To: Andrew Morton , Mike Rapoport , David Hildenbrand , Jonathan Corbet Cc: Peter Xu , "Liam R. Howlett" , Vlastimil Babka , Suren Baghdasaryan , Michal Hocko , Shuah Khan , Randy Dunlap , linux-mm@kvack.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Kiryl Shutsemau , Tal Zussman , Linus Torvalds , "Jose A. Perez de Azpillaga" Subject: [PATCH] Documentation/userfaultfd: document RWP behavior when the PTE is dropped Date: Fri, 13 Nov 2026 12:27:42 +0100 Message-ID: <20261113112806.109578-1-azpijr@gmail.com> X-Mailer: git-send-email 2.56.0 X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Scope of protection" lists only the PTE drops requested by the user and says the range has to be re-armed afterwards. On shmem the kernel drops the PTE as well (page reclaim, collapse), and RWP has no marker by design: the next access is a minor or a missing fault, and the user is expected to register for those. Document this, together with the modes that sync and async tracking need. The VMM example registers guest_mem with RWP and MISSING only, so a vCPU write to an offset that is not mapped there can be lost during eviction. Add MINOR to the registration and describe how the handler treats minor faults. Link: https://lore.kernel.org/linux-mm/856cdf21-7982-475a-b244-a7ceff4eb6aa@kernel.org/ Link: https://lore.kernel.org/linux-mm/avWnaR7VVEGa7yNp@thinkstation/ Suggested-by: Tal Zussman Signed-off-by: Jose A. Perez de Azpillaga --- this is the first time I'm writing documentation, so I accept any suggestions to improve it :) and I tried to follow the documentation's own style. Documentation/admin-guide/mm/userfaultfd.rst | 65 ++++++++++++++++---- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/Documentation/admin-guide/mm/userfaultfd.rst b/Documentation/admin-guide/mm/userfaultfd.rst index 97daea83b7f1..19bdac668f93 100644 --- a/Documentation/admin-guide/mm/userfaultfd.rst +++ b/Documentation/admin-guide/mm/userfaultfd.rst @@ -384,17 +384,45 @@ normal missing path (``do_anonymous_page()``, ``do_swap_page()``, the population itself, co-register the range with ``UFFDIO_REGISTER_MODE_MISSING``. -Protection is preserved across page reclaim: a page swapped out while -RWP-protected carries the marker on its swap entry, and swap-in restores -the PROT_NONE state so the first access after swap-in still faults. The -same applies to pages temporarily replaced by migration entries. - -Operations that drop the PTE entirely — ``MADV_DONTNEED`` on anonymous -memory, hole-punch on shmem, truncation of a file mapping — also drop the -RWP marker: the next access re-populates the range without protection. -Unlike WP (which persists via ``PTE_MARKER_UFFD_WP``), there is no -persistent RWP marker today. The user needs to re-arm the range with -``UFFDIO_RWPROTECT`` after any operation that explicitly frees PTEs. +Protection of anonymous memory is preserved across page reclaim: a page +swapped out while RWP-protected carries the marker on its swap entry, and +swap-in restores the PROT_NONE state so the first access after swap-in +still faults. The same applies to pages temporarily replaced by migration +entries. Shmem is different: reclaiming a shmem page leaves the PTE empty +rather than installing a swap entry, so the protection is dropped along +with the PTE. + +Operations that drop the PTE entirely also drop the RWP protection. Some +are requested by the user — ``MADV_DONTNEED``, hole-punch on shmem, +truncation of a file mapping — and some are initiated by the kernel on +shmem: page reclaim, and collapse into a huge page by khugepaged or +``MADV_COLLAPSE``. Unlike WP (which persists via ``PTE_MARKER_UFFD_WP``), +there is no persistent RWP marker, and this is intentional: once the PTE is +gone, the next access takes a page fault that userfaultfd can deliver, and +that fault is the notification. Which fault it is depends on what happened +to the page: + +- The page is still in the page cache or in swap: the access is a minor + fault, delivered if the range is co-registered with + ``UFFDIO_REGISTER_MODE_MINOR``. + +- The page is gone: the access is a missing fault, delivered if the range + is co-registered with ``UFFDIO_REGISTER_MODE_MISSING``. + +WP cannot use the same scheme — a minor fault would trap reads as well as +writes — which is why it needs a marker. + +Without the matching mode the page is mapped back silently and without +protection, so what to co-register depends on the tracking mode: + +- Sync mode: the access would be lost. Co-register shmem and hugetlbfs + ranges with ``UFFDIO_REGISTER_MODE_MINOR`` (and + ``UFFDIO_REGISTER_MODE_MISSING`` if the file can have holes), and + anonymous ranges, where minor faults are not available, with + ``UFFDIO_REGISTER_MODE_MISSING``. + +- Async mode: neither is needed. A page faulted back in is mapped without + the uffd bit, so ``PAGEMAP_SCAN`` reports it as accessed. **Fault Handling:** @@ -486,10 +514,16 @@ never traps on its own :: ioctl(uffd, UFFDIO_API, &api); if (!(api.features & UFFD_FEATURE_RWP)) /* RWP unavailable on this kernel/arch -- fall back. */ + /* + * MINOR: an offset in the page cache but not mapped in guest_mem + * would be mapped back without a fault, and a vCPU write between + * the pwrite() and the hole punch in step 4 would be lost. + */ ioctl(uffd, UFFDIO_REGISTER, &(struct uffdio_register){ .range = { guest_mem, guest_size }, .mode = UFFDIO_REGISTER_MODE_RWP | - UFFDIO_REGISTER_MODE_MISSING, + UFFDIO_REGISTER_MODE_MISSING | + UFFDIO_REGISTER_MODE_MINOR, }); /* Tracking loop */ @@ -550,6 +584,13 @@ progress. After ``fallocate()`` punches the page out and ``UFFDIO_WAKE`` fires, the vCPU retries the access, faults as ``MISSING``, and the handler resolves it with ``UFFDIO_COPY`` from storage. +The same holds for an offset being evicted that is not mapped in +``guest_mem``, except that the vCPU blocks with a +``UFFD_PAGEFAULT_FLAG_MINOR`` fault, which the handler leaves pending until +the page has been punched out. Minor faults on any other offset are +resolved with ``UFFDIO_CONTINUE``: the page is mapped without RWP +protection, so the next scan reports it as accessed. + This workflow targets shmem and hugetlbfs (both support a private ``io_mem`` mapping over the same fd). Anonymous-memory backings need a different inner-loop strategy because the VMM has no way to read the base-commit: 31a696f9c37defab0f28f774e00ac7f135889ec3 -- 2.56.0