From nobody Mon Sep 28 10:43:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3E28380FC6; Sun, 23 Aug 2026 12:17:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487478; cv=none; b=X+uQrsvCHSakkxQdQXdqUEmL0z5Yh8EK2Ft3bCKnKw9GqJHO0gdb849sFKQpR0HIjt3ni5ioA/FotxYqatszoDGEt3ObFafVlexnjPBvNcTa3ZvkhAf1POSr+AeUyV9bgra0Eza9waXK6ByUOV1mvR3aQlhz111LX8bk677ZHAU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487478; c=relaxed/simple; bh=31qEUMxCD1kfVB9JiEfF3V96sT9VroYttG2bG4L6wiY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YcWnXVv2GX7lQczgk4Pu7sCXCwVZ0J4L9zqtm8WRA3fSR+CvVuJlNY0GqzwTSuUCCEjG4rTr9pli1RahT+tn767oDpLWZ6kxqt2gxATCxxqp0KJ3GLPZQhlzlcNY7uX31MK7ynceo4vYka0+i4JSa7ylq1zXIxt3y5CblGJeHeQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JdB62QeL; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JdB62QeL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F9721F00A3A; Sun, 23 Aug 2026 12:17:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787487477; bh=phtAfk9967tvw5jCZ8EwhMxuR9BV70DOT2vnREg6Av0=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=JdB62QeLHfrgk01rU7saumkTHude9O5ljmTk8ojegK2RGvEuN1X6v0+bfsUBT3oC8 BrrdKyH8U+RenOUG0fNyJGhL761oH3Uggo6pqg/KnEcJ8gvjVzWNkQd+eUxp3Cy4nK ppxrXNG7PBxHFWlT9GuW0UhWK/ezVtolSz/FTRGF7LcYtPJHhV8w4QvIyFiT59gttD FqaZ/wlxuzjVHlojywG4R7foLh5P3doLWKkw0bKIj+L4G6DeZX6+lX3GRS653oR5vz Kjhrj0tTRMDE2EJm5T0PvMXlQSrTWVyAkH+VBPOJmvZAcUq17e1hyIlMUAmNPEIf1f EGV0bagWOWW5A== From: "Mike Rapoport (Microsoft)" Date: Sun, 23 Aug 2026 15:17:38 +0300 Subject: [PATCH 1/6] mm/gup: move gup_can_follow_protnone() to gup.c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260823-uffd-vm-flags-v1-v1-1-3086981b33cf@kernel.org> References: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> In-Reply-To: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> To: Andrew Morton , David Hildenbrand Cc: Baolin Wang , Barry Song , Dev Jain , Hugh Dickins , Jann Horn , Jason Gunthorpe , John Hubbard , Jonathan Corbet , Lance Yang , "Liam R. Howlett" , Lorenzo Stoakes , Masami Hiramatsu , Mathieu Desnoyers , Mike Rapoport , Michal Hocko , Muchun Song , Nico Pache , Oscar Salvador , Pedro Falcato , Peter Xu , Ryan Roberts , Shakeel Butt , Shuah Khan , Steven Rostedt , Suren Baghdasaryan , Usama Arif , Vlastimil Babka , Zi Yan , linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org X-Mailer: b4 0.17-dev gup_can_follow_protnone() is defined in include/linux/mm.h but only used by mm/gup.c. First, there is no reason to have it in already gigantic header. Next, the upcoming refactoring of userfaultfd flags will make gup_can_follow_protnone() depend on userfaultfd_k.h which would cause a cyclic header dependency. Move gup_can_follow_protnone() to mm/gup.c. No functional change. Assisted-by: copilot:claude-opus-5 Signed-off-by: Mike Rapoport (Microsoft) Acked-by: David Hildenbrand (Arm) Reviewed-by: Barry Song Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Zi Yan --- include/linux/mm.h | 38 -------------------------------------- mm/gup.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 0829e0d3b2d1..4daf9cd6ae8e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4860,44 +4860,6 @@ static inline int vm_fault_to_errno(vm_fault_t vm_fa= ult, int foll_flags) return 0; } =20 -/* - * Indicates whether GUP can follow a PROT_NONE mapped page, or whether - * a (NUMA hinting or userfaultfd RWP) fault is required. - */ -static inline bool gup_can_follow_protnone(const struct vm_area_struct *vm= a, - unsigned int flags) -{ - /* - * VM_UFFD_RWP uses protnone as an access-tracking marker, not for - * NUMA hinting. GUP must always take a fault so the access is - * delivered to userfaultfd, regardless of FOLL_HONOR_NUMA_FAULT. - * - * Only do so while the VMA is accessible. If it has been made - * inaccessible (e.g. mprotect(PROT_NONE)), fall through to the guard - * below: forcing a fault there would loop, as handle_mm_fault() makes - * no progress on protnone in an inaccessible VMA, and the access is - * denied regardless of RWP anyway. - */ - if (vma_test_single_mask(vma, VMA_UFFD_RWP) && vma_is_accessible(vma)) - return false; - - /* - * If callers don't want to honor NUMA hinting faults, no need to - * determine if we would actually have to trigger a NUMA hinting fault. - */ - if (!(flags & FOLL_HONOR_NUMA_FAULT)) - return true; - - /* - * NUMA hinting faults don't apply in inaccessible (PROT_NONE) VMAs. - * - * Requiring a fault here even for inaccessible VMAs would mean that - * FOLL_FORCE cannot make any progress, because handle_mm_fault() - * refuses to process NUMA hinting faults in inaccessible VMAs. - */ - return !vma_is_accessible(vma); -} - typedef int (*pte_fn_t)(pte_t *pte, unsigned long addr, void *data); extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, unsigned long size, pte_fn_t fn, void *data); diff --git a/mm/gup.c b/mm/gup.c index eb898ea1ee22..500e2aa99e48 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -633,6 +633,44 @@ static struct page *no_page_table(struct vm_area_struc= t *vma, return NULL; } =20 +/* + * Indicates whether GUP can follow a PROT_NONE mapped page, or whether + * a (NUMA hinting or userfaultfd RWP) fault is required. + */ +static inline bool gup_can_follow_protnone(const struct vm_area_struct *vm= a, + unsigned int flags) +{ + /* + * VM_UFFD_RWP uses protnone as an access-tracking marker, not for + * NUMA hinting. GUP must always take a fault so the access is + * delivered to userfaultfd, regardless of FOLL_HONOR_NUMA_FAULT. + * + * Only do so while the VMA is accessible. If it has been made + * inaccessible (e.g. mprotect(PROT_NONE)), fall through to the guard + * below: forcing a fault there would loop, as handle_mm_fault() makes + * no progress on protnone in an inaccessible VMA, and the access is + * denied regardless of RWP anyway. + */ + if (vma_test_single_mask(vma, VMA_UFFD_RWP) && vma_is_accessible(vma)) + return false; + + /* + * If callers don't want to honor NUMA hinting faults, no need to + * determine if we would actually have to trigger a NUMA hinting fault. + */ + if (!(flags & FOLL_HONOR_NUMA_FAULT)) + return true; + + /* + * NUMA hinting faults don't apply in inaccessible (PROT_NONE) VMAs. + * + * Requiring a fault here even for inaccessible VMAs would mean that + * FOLL_FORCE cannot make any progress, because handle_mm_fault() + * refuses to process NUMA hinting faults in inaccessible VMAs. + */ + return !vma_is_accessible(vma); +} + #ifdef CONFIG_PGTABLE_HAS_HUGE_LEAVES /* FOLL_FORCE can write to even unwritable PUDs in COW mappings. */ static inline bool can_follow_write_pud(pud_t pud, struct page *page, --=20 2.53.0 From nobody Mon Sep 28 10:43:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A7D9370AC0; Sun, 23 Aug 2026 12:18:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487486; cv=none; b=O/kbGAvhKUBhNp5moZeLlBrjYZv5l5IyBriB4J8XYg8Z0SrHWVLFY0yr8HnWYYdOcu/yCsQgv9gbgGKLDvuLgzAzFYPjvIO4W7gpoO2CrNBrfVF+iczozC5rdjMkS1hWR93p8bcE4QGc+aTOzxOYukAfxYkiifxCQGt7+2hNgHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487486; c=relaxed/simple; bh=dbBYm+aOrSlQd/YFVsrZ8xIVQNUwkL/QqULON7EGjzU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=crr57pdsVuvE9HeBP1b4m67KTXAel9KShjWgFLlNWpPe/65tfWcBvuUIcDjiJHJqpNuq4G8RRTQFeZ7vzRLiJel1Cu+0QiVrVMTjIfmPVeSerp4ugbsdvyft9zxDeSrNBJARHlR97UHebwYc6t97gW+Hy/1gKpI0FitgUATdJqs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hh4r+QK2; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hh4r+QK2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98DCB1F000E9; Sun, 23 Aug 2026 12:17:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787487485; bh=kndwtv5Cm5Svk82exojGXyoNLdRzxaTi6Z5eoExMZW8=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Hh4r+QK2GdpFEuv6ihYd8/+0ZW1NQU+UeKZdTxUMtpnRo78N4CPidoNDY5bHIHEh7 R2QKLcipnEJbDJbbS/Dryi1+nkvs1RVC1oV64SnN7k2nbxm32zx8oGLesqLons5Z1x 2N743kbgL182hjg41CyjOn542aZh8zZCGbLPjXBGPpUuHth2xsSL+YIvT3nZoXK0qB nyoOjCJERvpXxA2wQcf5+ArmjXQXhaDd1jr/iBCUxiuFkUuo6Bany7IjY+sHLJobD7 kWXhJOkJCu06p9sKN9b9omMLEuVZzBXGdQqUa6awxh/fuEgRLWRTd6XAExltaipQcH DRctSy1CvIbDw== From: "Mike Rapoport (Microsoft)" Date: Sun, 23 Aug 2026 15:17:39 +0300 Subject: [PATCH 2/6] userfaultfd: constify VMA parameter of userfaultfd_*() helpers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260823-uffd-vm-flags-v1-v1-2-3086981b33cf@kernel.org> References: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> In-Reply-To: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> To: Andrew Morton , David Hildenbrand Cc: Baolin Wang , Barry Song , Dev Jain , Hugh Dickins , Jann Horn , Jason Gunthorpe , John Hubbard , Jonathan Corbet , Lance Yang , "Liam R. Howlett" , Lorenzo Stoakes , Masami Hiramatsu , Mathieu Desnoyers , Mike Rapoport , Michal Hocko , Muchun Song , Nico Pache , Oscar Salvador , Pedro Falcato , Peter Xu , Ryan Roberts , Shakeel Butt , Shuah Khan , Steven Rostedt , Suren Baghdasaryan , Usama Arif , Vlastimil Babka , Zi Yan , linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org X-Mailer: b4 0.17-dev userfaultfd_{missing,wp,minor,rwp}() and userfaultfd_protected() only read the VMA. Make their vma parameter const. No functional change. Assisted-by: copilot:claude-opus-5 Signed-off-by: Mike Rapoport (Microsoft) Reviewed-by: Barry Song Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Zi Yan --- include/linux/userfaultfd_k.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index a4351cffc60c..3396d270b159 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -204,22 +204,22 @@ static inline bool uffd_disable_fault_around(struct v= m_area_struct *vma) VMA_UFFD_MINOR)); } =20 -static inline bool userfaultfd_missing(struct vm_area_struct *vma) +static inline bool userfaultfd_missing(const struct vm_area_struct *vma) { return vma_test_any_mask(vma, VMA_UFFD_MISSING); } =20 -static inline bool userfaultfd_wp(struct vm_area_struct *vma) +static inline bool userfaultfd_wp(const struct vm_area_struct *vma) { return vma_test_any_mask(vma, VMA_UFFD_WP); } =20 -static inline bool userfaultfd_minor(struct vm_area_struct *vma) +static inline bool userfaultfd_minor(const struct vm_area_struct *vma) { return vma_test_any_mask(vma, VMA_UFFD_MINOR); } =20 -static inline bool userfaultfd_rwp(struct vm_area_struct *vma) +static inline bool userfaultfd_rwp(const struct vm_area_struct *vma) { /* * Callers gate PAGE_NONE usage on this; PAGE_NONE is a BUILD_BUG() @@ -230,7 +230,7 @@ static inline bool userfaultfd_rwp(struct vm_area_struc= t *vma) return vma_test_single_mask(vma, VMA_UFFD_RWP); } =20 -static inline bool userfaultfd_protected(struct vm_area_struct *vma) +static inline bool userfaultfd_protected(const struct vm_area_struct *vma) { return userfaultfd_wp(vma) || userfaultfd_rwp(vma); } @@ -353,27 +353,27 @@ static inline bool is_mergeable_vm_userfaultfd_ctx(st= ruct vm_area_struct *vma, return true; } =20 -static inline bool userfaultfd_missing(struct vm_area_struct *vma) +static inline bool userfaultfd_missing(const struct vm_area_struct *vma) { return false; } =20 -static inline bool userfaultfd_wp(struct vm_area_struct *vma) +static inline bool userfaultfd_wp(const struct vm_area_struct *vma) { return false; } =20 -static inline bool userfaultfd_minor(struct vm_area_struct *vma) +static inline bool userfaultfd_minor(const struct vm_area_struct *vma) { return false; } =20 -static inline bool userfaultfd_rwp(struct vm_area_struct *vma) +static inline bool userfaultfd_rwp(const struct vm_area_struct *vma) { return false; } =20 -static inline bool userfaultfd_protected(struct vm_area_struct *vma) +static inline bool userfaultfd_protected(const struct vm_area_struct *vma) { return false; } --=20 2.53.0 From nobody Mon Sep 28 10:43:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7E5D5380FC6; Sun, 23 Aug 2026 12:18:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487494; cv=none; b=o3KNTHmWj2gdZ7FF6qV6+cFYRjWDfljBbWFyVledC8S+3qVC2daQPQC2uT+WcqvmpVMU32Cv7CYHegj6Wu1pqHuy0Q8llsEm6rFcH4bLLYXeclDFPv5v1SsW+0g5E8lOUaK1zxQ2w9O0d+p72UT3W/5KDY/4+YV1d07f+qn7w6Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487494; c=relaxed/simple; bh=Qg7yx77FSVBEj+CsfPgiLo7sYpsRpr/h5Y+cKLlLcrE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IJ8w3Ino5mx2yjGVfzPLsfldbIRNNbwQoUzZEhoEE1/xcTmmtFaytNtGtpaObm2r0z6+0ElcdznJtmzpedM1FC0QGu8Sn3lYouP9pgqc6t3NU23cIGKIOqQKCExBXDeEZsR42NZidofd8n5K0eUNueGIolb4uYMmQlIqXrwKZ20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g1iX059/; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g1iX059/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8BB31F00A3A; Sun, 23 Aug 2026 12:18:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787487493; bh=nPcwKjVe7nvZQyU74ZGx+OhASVw5VhjTqdhj+ioxLpo=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=g1iX059/4fd671ipoP1cbd8ep4SvuMjBn2cP6Nmd1GFSZz4JBgseMsWqA3UYSw0An HQRWbf0n89PZVfi9hwgTvOF3htN9Dwr2umNmTOcziuGSoCxI6MrTZDkJonFATEkoXu bOUH7gWOBRjroBmd9mMq+HVynUNmUXmAk3TcKzFkUV5z0NK6tKfCBzg528GuJtHtm3 1XHuHpTTiAWfznjJ2OKA6uRkSHTeREfiJNjVC/jBH7YeanuaqHH+/u6L0Rw0uHETqZ kOywUx3JSn3XISIR1I+COtEeys1DRIiGtfh/TxvThI1iwPvEISDqM8MZJgZnUoDJ+y J3FXqk71iVqwQ== From: "Mike Rapoport (Microsoft)" Date: Sun, 23 Aug 2026 15:17:40 +0300 Subject: [PATCH 3/6] userfaultfd: use userfaultfd_*() helpers instead of open coded flag tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260823-uffd-vm-flags-v1-v1-3-3086981b33cf@kernel.org> References: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> In-Reply-To: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> To: Andrew Morton , David Hildenbrand Cc: Baolin Wang , Barry Song , Dev Jain , Hugh Dickins , Jann Horn , Jason Gunthorpe , John Hubbard , Jonathan Corbet , Lance Yang , "Liam R. Howlett" , Lorenzo Stoakes , Masami Hiramatsu , Mathieu Desnoyers , Mike Rapoport , Michal Hocko , Muchun Song , Nico Pache , Oscar Salvador , Pedro Falcato , Peter Xu , Ryan Roberts , Shakeel Butt , Shuah Khan , Steven Rostedt , Suren Baghdasaryan , Usama Arif , Vlastimil Babka , Zi Yan , linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org X-Mailer: b4 0.17-dev Move userfaultfd_{missing,wp,minor,rwp}() and userfaultfd_protected() ahead of uffd_disable_huge_pmd_share() and uffd_disable_fault_around() and make the latter two use the helpers rather than open coded VMA flag masks. Convert open coded VMA flag test in mfill_get_vma() to userfaultfd_wp() as well. With every user of the per-VMA uffd modes going through the helpers, their underlying representation can be changed in the next step. No functional change. Assisted-by: copilot:claude-opus-5 Signed-off-by: Mike Rapoport (Microsoft) Reviewed-by: Barry Song --- include/linux/userfaultfd_k.h | 70 +++++++++++++++++++++------------------= ---- mm/userfaultfd.c | 2 +- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index 3396d270b159..d8262e3dc134 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -168,42 +168,6 @@ static inline bool is_mergeable_vm_userfaultfd_ctx(str= uct vm_area_struct *vma, return vma->vm_userfaultfd_ctx.ctx =3D=3D vm_ctx.ctx; } =20 -/* - * Never enable huge pmd sharing on some uffd registered vmas: - * - * - VM_UFFD_WP and VM_UFFD_RWP VMAs, because the write protect / access - * tracking information is per pgtable entry. - * - * - VM_UFFD_MINOR VMAs, because otherwise we would never get minor faults= for - * VMAs which share huge pmds. (If you have two mappings to the same - * underlying pages, and fault in the non-UFFD-registered one with a wri= te, - * with huge pmd sharing this would *also* setup the second UFFD-registe= red - * mapping, and we'd not get minor faults.) - */ -static inline bool uffd_disable_huge_pmd_share(struct vm_area_struct *vma) -{ - return vma_test_any_mask(vma, - mk_vma_flags_from_masks(VMA_UFFD_WP, VMA_UFFD_RWP, - VMA_UFFD_MINOR)); -} - -/* - * Don't do fault around for WP, RWP or MINOR registered uffd range. For - * MINOR registered range, fault around will be a total disaster and ptes = can - * be installed without notifications; for WP it should mostly be fine as = long - * as the fault around checks for pte_none() before the installation, howe= ver - * to be super safe we just forbid it; for RWP, pre-faulted neighbours wou= ld - * be indistinguishable from accessed pages in PAGEMAP_SCAN (PAGE_IS_ACCES= SED) - * and pollute the tracked working set, so each page must be populated by = its - * own fault. - */ -static inline bool uffd_disable_fault_around(struct vm_area_struct *vma) -{ - return vma_test_any_mask(vma, - mk_vma_flags_from_masks(VMA_UFFD_WP, VMA_UFFD_RWP, - VMA_UFFD_MINOR)); -} - static inline bool userfaultfd_missing(const struct vm_area_struct *vma) { return vma_test_any_mask(vma, VMA_UFFD_MISSING); @@ -235,6 +199,40 @@ static inline bool userfaultfd_protected(const struct = vm_area_struct *vma) return userfaultfd_wp(vma) || userfaultfd_rwp(vma); } =20 +/* + * Never enable huge pmd sharing on some uffd registered vmas: + * + * - uffd-WP and uffd-RWP VMAs, because the write protect / access tracking + * information is per pgtable entry. + * + * - uffd-MINOR VMAs, because otherwise we would never get minor faults for + * VMAs which share huge pmds. (If you have two mappings to the same + * underlying pages, and fault in the non-UFFD-registered one with a wri= te, + * with huge pmd sharing this would *also* setup the second UFFD-registe= red + * mapping, and we'd not get minor faults.) + */ +static inline bool uffd_disable_huge_pmd_share(struct vm_area_struct *vma) +{ + return userfaultfd_minor(vma) || userfaultfd_wp(vma) || + userfaultfd_rwp(vma); +} + +/* + * Don't do fault around for WP, RWP or MINOR registered uffd range. For + * MINOR registered range, fault around will be a total disaster and ptes = can + * be installed without notifications; for WP it should mostly be fine as = long + * as the fault around checks for pte_none() before the installation, howe= ver + * to be super safe we just forbid it; for RWP, pre-faulted neighbours wou= ld + * be indistinguishable from accessed pages in PAGEMAP_SCAN (PAGE_IS_ACCES= SED) + * and pollute the tracked working set, so each page must be populated by = its + * own fault. + */ +static inline bool uffd_disable_fault_around(struct vm_area_struct *vma) +{ + return userfaultfd_minor(vma) || userfaultfd_wp(vma) || + userfaultfd_rwp(vma); +} + static inline bool userfaultfd_pte_wp(struct vm_area_struct *vma, pte_t pte) { diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 74f04c323c50..32003aa04943 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -261,7 +261,7 @@ static int mfill_get_vma(struct mfill_state *state) * validate 'mode' now that we know the dst_vma: don't allow * a wrprotect copy if the userfaultfd didn't register as WP. */ - if ((flags & MFILL_ATOMIC_WP) && !(dst_vma->vm_flags & VM_UFFD_WP)) + if ((flags & MFILL_ATOMIC_WP) && !userfaultfd_wp(dst_vma)) goto out_unlock; =20 if (is_vm_hugetlb_page(dst_vma)) --=20 2.53.0 From nobody Mon Sep 28 10:43:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 334433D1CAF; Sun, 23 Aug 2026 12:18:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487504; cv=none; b=F3XjGOqlF7JaDk0YYx2D08rf/N96mmD74ApOBnhjYtI9HflGoMNvdVbogjgt8Kbd+gBhjKgf8k68nD5NueiMkp6ivpYtOv1i6TWGCxOiOwlpR/kP9M/tccbJUbSwSR0zGO/qolVedsDheW6B1B22SK+l5oIclcLVnKv4kQWOGPU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487504; c=relaxed/simple; bh=bmdCLa+wUfMabOr0G1eIb3RSPxxYjGcawGnzEvbf7GI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=n5iAJdJlMMpiYDjBfqAU5nN4+HS57v44Njcsm2SBKHO3diOrZwzgUki+Yiq1bg+w6rPBik9NhVD8psiiJkjZzpJ+gwWhY95CARagF69b3Wbm196uWZ2Ikd233hBxVJSq5WjYxZihd1XVODoYT8HPDlOgL9kqD1GTL0Swnrslndo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J2UBVhzD; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="J2UBVhzD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E1C851F000E9; Sun, 23 Aug 2026 12:18:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787487501; bh=woEWVJb5MiHnHp1LOW/gK5/BrTOnz81Ub7hty9cTHwg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=J2UBVhzD+q+ud6E1L/0A2zmqcBIlHC7eaNbjYiHGPxh2aOEy9eG9L/CmLEp/ulKEa V0W4qg9loQtHVbupqpWd6cFeTwcNFmmge4L9mt5+SKUZsC5QiTBd6e7ekYZ++yFlH3 leZ+t7a5gocV9lZhKkFM8+f+k9v0ZfSu+tOEsLyIv5lw1JVoVd0nOGCnDhMpDaJV1p LwCYKHilJbk3R79gQ2pJN88haIs2zZMg8jFSD4jjJYxBA2Jn8/Ofb8oUtDzCzqY7WK S0Rmfj31zrAJUCTRYVH7f0W9B/PLLgOEXXsZhJFEUKCvdU7WjD7S0vJwIX//G9IEN5 40Fj4HW1xTEcw== From: "Mike Rapoport (Microsoft)" Date: Sun, 23 Aug 2026 15:17:41 +0300 Subject: [PATCH 4/6] userfaultfd: rename vm_userfaultfd_ctx to vm_uffd_state Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260823-uffd-vm-flags-v1-v1-4-3086981b33cf@kernel.org> References: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> In-Reply-To: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> To: Andrew Morton , David Hildenbrand Cc: Baolin Wang , Barry Song , Dev Jain , Hugh Dickins , Jann Horn , Jason Gunthorpe , John Hubbard , Jonathan Corbet , Lance Yang , "Liam R. Howlett" , Lorenzo Stoakes , Masami Hiramatsu , Mathieu Desnoyers , Mike Rapoport , Michal Hocko , Muchun Song , Nico Pache , Oscar Salvador , Pedro Falcato , Peter Xu , Ryan Roberts , Shakeel Butt , Shuah Khan , Steven Rostedt , Suren Baghdasaryan , Usama Arif , Vlastimil Babka , Zi Yan , linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org X-Mailer: b4 0.17-dev Rename struct vm_userfaultfd_ctx to vm_uffd_state to better reflect that it will represent the userfaultfd state for a VMA rather than just a context pointer. This is a preparatory step for extending the struct with a mode field. Mechanical rename, no functional change. Assisted-by: copilot:claude-opus-4.6 Signed-off-by: Mike Rapoport (Microsoft) Acked-by: David Hildenbrand (Arm) Reviewed-by: Lorenzo Stoakes (ARM) --- Documentation/mm/process_addrs.rst | 4 +-- include/linux/mm_types.h | 10 +++--- include/linux/userfaultfd_k.h | 24 ++++++------- mm/mremap.c | 4 +-- mm/userfaultfd.c | 74 +++++++++++++++++++---------------= ---- mm/vma.c | 4 +-- mm/vma.h | 6 ++-- mm/vma_init.c | 4 +-- tools/testing/vma/include/dup.h | 2 +- tools/testing/vma/include/stubs.h | 6 ++-- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/Documentation/mm/process_addrs.rst b/Documentation/mm/process_= addrs.rst index a7296f251799..481e9435e4e8 100644 --- a/Documentation/mm/process_addrs.rst +++ b/Documentation/mm/process_addrs.rst @@ -229,8 +229,8 @@ These are the core fields which describe the MM the VMA= belongs to and its attri NUMA balancing = in relation to this VMA. lock. Updated under m= map read lock by :c:func:`!task_= numa_work`. - :c:member:`!vm_userfaultfd_ctx` CONFIG_USERFAULTFD Userfaultfd con= text wrapper object of mmap write, - type :c:type:`!= vm_userfaultfd_ctx`, VMA write. + :c:member:`!vm_uffd_state` CONFIG_USERFAULTFD Userfaultfd con= text wrapper object of mmap write, + type :c:type:`!= vm_uffd_state`, VMA write. either of zero = size if userfaultfd is disabled, or co= ntaining a pointer to an underlying diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 6d815f6440c9..d6deb655d82e 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -720,13 +720,13 @@ struct vm_region { }; =20 #ifdef CONFIG_USERFAULTFD -#define NULL_VM_UFFD_CTX ((struct vm_userfaultfd_ctx) { NULL, }) -struct vm_userfaultfd_ctx { +#define NULL_VM_UFFD_STATE ((struct vm_uffd_state) { NULL, }) +struct vm_uffd_state { struct userfaultfd_ctx *ctx; }; #else /* CONFIG_USERFAULTFD */ -#define NULL_VM_UFFD_CTX ((struct vm_userfaultfd_ctx) {}) -struct vm_userfaultfd_ctx {}; +#define NULL_VM_UFFD_STATE ((struct vm_uffd_state) {}) +struct vm_uffd_state {}; #endif /* CONFIG_USERFAULTFD */ =20 struct anon_vma_name { @@ -1071,7 +1071,7 @@ struct vm_area_struct { */ struct anon_vma_name *anon_name; #endif - struct vm_userfaultfd_ctx vm_userfaultfd_ctx; + struct vm_uffd_state vm_uffd_state; #ifdef __HAVE_PFNMAP_TRACKING struct pfnmap_track_ctx *pfnmap_track_ctx; #endif diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index d8262e3dc134..45355bdb4ec7 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -162,10 +162,10 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *= dst_pmd, pmd_t *src_pmd, pm unsigned long dst_addr, unsigned long src_addr); =20 /* mm helpers */ -static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *= vma, - struct vm_userfaultfd_ctx vm_ctx) +static inline bool is_mergeable_vm_uffd_state(struct vm_area_struct *vma, + struct vm_uffd_state vm_ctx) { - return vma->vm_userfaultfd_ctx.ctx =3D=3D vm_ctx.ctx; + return vma->vm_uffd_state.ctx =3D=3D vm_ctx.ctx; } =20 static inline bool userfaultfd_missing(const struct vm_area_struct *vma) @@ -264,7 +264,7 @@ static inline bool userfaultfd_armed(struct vm_area_str= uct *vma) =20 static inline bool vma_has_uffd_without_event_remap(struct vm_area_struct = *vma) { - struct userfaultfd_ctx *uffd_ctx =3D vma->vm_userfaultfd_ctx.ctx; + struct userfaultfd_ctx *uffd_ctx =3D vma->vm_uffd_state.ctx; =20 return uffd_ctx && (uffd_ctx->features & UFFD_FEATURE_EVENT_REMAP) =3D=3D= 0; } @@ -274,11 +274,11 @@ extern void dup_userfaultfd_complete(struct list_head= *); void dup_userfaultfd_fail(struct list_head *); =20 extern void mremap_userfaultfd_prep(struct vm_area_struct *, - struct vm_userfaultfd_ctx *); -extern void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *, + struct vm_uffd_state *); +extern void mremap_userfaultfd_complete(struct vm_uffd_state *, unsigned long from, unsigned long to, unsigned long len); -void mremap_userfaultfd_fail(struct vm_userfaultfd_ctx *); +void mremap_userfaultfd_fail(struct vm_uffd_state *); =20 extern bool userfaultfd_remove(struct vm_area_struct *vma, unsigned long start, @@ -345,8 +345,8 @@ static inline long uffd_wp_range(struct vm_area_struct = *vma, return false; } =20 -static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *= vma, - struct vm_userfaultfd_ctx vm_ctx) +static inline bool is_mergeable_vm_uffd_state(struct vm_area_struct *vma, + struct vm_uffd_state vm_ctx) { return true; } @@ -420,18 +420,18 @@ static inline void dup_userfaultfd_fail(struct list_h= ead *l) } =20 static inline void mremap_userfaultfd_prep(struct vm_area_struct *vma, - struct vm_userfaultfd_ctx *ctx) + struct vm_uffd_state *ctx) { } =20 -static inline void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *= ctx, +static inline void mremap_userfaultfd_complete(struct vm_uffd_state *ctx, unsigned long from, unsigned long to, unsigned long len) { } =20 -static inline void mremap_userfaultfd_fail(struct vm_userfaultfd_ctx *ctx) +static inline void mremap_userfaultfd_fail(struct vm_uffd_state *ctx) { } =20 diff --git a/mm/mremap.c b/mm/mremap.c index e8df5cdb0ac9..a4a38f30b255 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -56,7 +56,7 @@ struct vma_remap_struct { unsigned long new_addr; /* Optionally, desired new address. */ =20 /* uffd state. */ - struct vm_userfaultfd_ctx *uf; + struct vm_uffd_state *uf; struct list_head *uf_unmap_early; struct list_head *uf_unmap; =20 @@ -2033,7 +2033,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned= long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr) { - struct vm_userfaultfd_ctx uf =3D NULL_VM_UFFD_CTX; + struct vm_uffd_state uf =3D NULL_VM_UFFD_STATE; LIST_HEAD(uf_unmap_early); LIST_HEAD(uf_unmap); /* diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 32003aa04943..119304547230 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -99,7 +99,7 @@ bool validate_dst_vma(struct vm_area_struct *dst_vma, uns= igned long dst_end) * enforce the VM_MAYWRITE check done at uffd registration * time. */ - if (!dst_vma->vm_userfaultfd_ctx.ctx) + if (!dst_vma->vm_uffd_state.ctx) return false; =20 return true; @@ -1812,8 +1812,8 @@ static int validate_move_areas(struct userfaultfd_ctx= *ctx, return -EINVAL; =20 /* Ensure dst_vma is registered in uffd we are operating on */ - if (!dst_vma->vm_userfaultfd_ctx.ctx || - dst_vma->vm_userfaultfd_ctx.ctx !=3D ctx) + if (!dst_vma->vm_uffd_state.ctx || + dst_vma->vm_uffd_state.ctx !=3D ctx) return -EINVAL; =20 /* Only allow moving across anonymous vmas */ @@ -2249,7 +2249,7 @@ static void userfaultfd_set_ctx(struct vm_area_struct= *vma, vm_flags_t vm_flags) { vma_start_write(vma); - vma->vm_userfaultfd_ctx =3D (struct vm_userfaultfd_ctx){ctx}; + vma->vm_uffd_state =3D (struct vm_uffd_state){ctx}; userfaultfd_set_vm_flags(vma, (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags); } @@ -2296,7 +2296,7 @@ static struct vm_area_struct *userfaultfd_clear_vma(s= truct vma_iterator *vmi, } =20 ret =3D vma_modify_flags_uffd(vmi, prev, vma, start, end, - &new_vma_flags, NULL_VM_UFFD_CTX, + &new_vma_flags, NULL_VM_UFFD_STATE, give_up_on_oom); =20 /* @@ -2330,15 +2330,15 @@ static int userfaultfd_register_range(struct userfa= ultfd_ctx *ctx, cond_resched(); =20 VM_WARN_ON_ONCE(!vma_can_userfault(vma, vm_flags, wp_async)); - VM_WARN_ON_ONCE(vma->vm_userfaultfd_ctx.ctx && - vma->vm_userfaultfd_ctx.ctx !=3D ctx); + VM_WARN_ON_ONCE(vma->vm_uffd_state.ctx && + vma->vm_uffd_state.ctx !=3D ctx); VM_WARN_ON_ONCE(!vma_test(vma, VMA_MAYWRITE_BIT)); =20 /* * Nothing to do: this vma is already registered into this * userfaultfd and with the right tracking mode too. */ - if (vma->vm_userfaultfd_ctx.ctx =3D=3D ctx && + if (vma->vm_uffd_state.ctx =3D=3D ctx && vma_test_all_mask(vma, vma_flags)) goto skip; =20 @@ -2347,7 +2347,7 @@ static int userfaultfd_register_range(struct userfaul= tfd_ctx *ctx, * switches that would drop VM_UFFD_WP or VM_UFFD_RWP, so a * stray bit here is a bug. */ - VM_WARN_ON_ONCE(vma->vm_userfaultfd_ctx.ctx =3D=3D ctx && + VM_WARN_ON_ONCE(vma->vm_uffd_state.ctx =3D=3D ctx && vma->vm_flags & (VM_UFFD_WP | VM_UFFD_RWP) & ~vm_flags); =20 if (vma->vm_start > start) @@ -2360,7 +2360,7 @@ static int userfaultfd_register_range(struct userfaul= tfd_ctx *ctx, =20 vma =3D vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, &new_vma_flags, - (struct vm_userfaultfd_ctx){ctx}, + (struct vm_uffd_state){ctx}, /* give_up_on_oom =3D */false); if (IS_ERR(vma)) return PTR_ERR(vma); @@ -2389,10 +2389,10 @@ static void userfaultfd_release_new(struct userfaul= tfd_ctx *ctx) struct vm_area_struct *vma; VMA_ITERATOR(vmi, mm, 0); =20 - /* the various vma->vm_userfaultfd_ctx still points to it */ + /* the various vma->vm_uffd_state still points to it */ mmap_write_lock(mm); for_each_vma(vmi, vma) { - if (vma->vm_userfaultfd_ctx.ctx =3D=3D ctx) + if (vma->vm_uffd_state.ctx =3D=3D ctx) userfaultfd_reset_ctx(vma); } mmap_write_unlock(mm); @@ -2419,9 +2419,9 @@ static void userfaultfd_release_all(struct mm_struct = *mm, prev =3D NULL; for_each_vma(vmi, vma) { cond_resched(); - VM_WARN_ON_ONCE(!!vma->vm_userfaultfd_ctx.ctx ^ + VM_WARN_ON_ONCE(!!vma->vm_uffd_state.ctx ^ !!(vma->vm_flags & __VM_UFFD_FLAGS)); - if (vma->vm_userfaultfd_ctx.ctx !=3D ctx) { + if (vma->vm_uffd_state.ctx !=3D ctx) { prev =3D vma; continue; } @@ -2512,7 +2512,7 @@ static bool userfaultfd_rwp_async_ctx(struct userfaul= tfd_ctx *ctx) */ bool userfaultfd_wp_unpopulated(struct vm_area_struct *vma) { - struct userfaultfd_ctx *ctx =3D vma->vm_userfaultfd_ctx.ctx; + struct userfaultfd_ctx *ctx =3D vma->vm_uffd_state.ctx; =20 if (!ctx) return false; @@ -2854,7 +2854,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, uns= igned long reason) =20 assert_fault_locked(vmf); =20 - ctx =3D vma->vm_userfaultfd_ctx.ctx; + ctx =3D vma->vm_uffd_state.ctx; if (!ctx) goto out; =20 @@ -3094,7 +3094,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struc= t list_head *fcs) struct userfaultfd_ctx *ctx =3D NULL, *octx; struct userfaultfd_fork_ctx *fctx; =20 - octx =3D vma->vm_userfaultfd_ctx.ctx; + octx =3D vma->vm_uffd_state.ctx; if (!octx) return 0; =20 @@ -3138,7 +3138,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struc= t list_head *fcs) list_add_tail(&fctx->list, fcs); } =20 - vma->vm_userfaultfd_ctx.ctx =3D ctx; + vma->vm_uffd_state.ctx =3D ctx; return 0; } =20 @@ -3195,11 +3195,11 @@ void dup_userfaultfd_fail(struct list_head *fcs) } =20 void mremap_userfaultfd_prep(struct vm_area_struct *vma, - struct vm_userfaultfd_ctx *vm_ctx) + struct vm_uffd_state *vm_ctx) { struct userfaultfd_ctx *ctx; =20 - ctx =3D vma->vm_userfaultfd_ctx.ctx; + ctx =3D vma->vm_uffd_state.ctx; =20 if (!ctx) return; @@ -3216,7 +3216,7 @@ void mremap_userfaultfd_prep(struct vm_area_struct *v= ma, } } =20 -void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *vm_ctx, +void mremap_userfaultfd_complete(struct vm_uffd_state *vm_ctx, unsigned long from, unsigned long to, unsigned long len) { @@ -3236,7 +3236,7 @@ void mremap_userfaultfd_complete(struct vm_userfaultf= d_ctx *vm_ctx, userfaultfd_event_wait_completion(ctx, &ewq); } =20 -void mremap_userfaultfd_fail(struct vm_userfaultfd_ctx *vm_ctx) +void mremap_userfaultfd_fail(struct vm_uffd_state *vm_ctx) { struct userfaultfd_ctx *ctx =3D vm_ctx->ctx; =20 @@ -3255,7 +3255,7 @@ bool userfaultfd_remove(struct vm_area_struct *vma, struct userfaultfd_ctx *ctx; struct userfaultfd_wait_queue ewq; =20 - ctx =3D vma->vm_userfaultfd_ctx.ctx; + ctx =3D vma->vm_uffd_state.ctx; if (!ctx || !(ctx->features & UFFD_FEATURE_EVENT_REMOVE)) return true; =20 @@ -3293,7 +3293,7 @@ int userfaultfd_unmap_prep(struct vm_area_struct *vma= , unsigned long start, unsigned long end, struct list_head *unmaps) { struct userfaultfd_unmap_ctx *unmap_ctx; - struct userfaultfd_ctx *ctx =3D vma->vm_userfaultfd_ctx.ctx; + struct userfaultfd_ctx *ctx =3D vma->vm_uffd_state.ctx; =20 if (!ctx || !(ctx->features & UFFD_FEATURE_EVENT_UNMAP) || has_unmap_ctx(ctx, unmaps, start, end)) @@ -3813,7 +3813,7 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, do { cond_resched(); =20 - VM_WARN_ON_ONCE(!!cur->vm_userfaultfd_ctx.ctx ^ + VM_WARN_ON_ONCE(!!cur->vm_uffd_state.ctx ^ !!(cur->vm_flags & __VM_UFFD_FLAGS)); =20 /* check not compatible vmas */ @@ -3867,8 +3867,8 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, * wouldn't know which one to deliver the userfaults to. */ ret =3D -EBUSY; - if (cur->vm_userfaultfd_ctx.ctx && - cur->vm_userfaultfd_ctx.ctx !=3D ctx) + if (cur->vm_uffd_state.ctx && + cur->vm_uffd_state.ctx !=3D ctx) goto out_unlock; =20 /* @@ -3877,7 +3877,7 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, * subsequent mprotect() would then promote stale markers * into the other mode. Require an unregister first. */ - if (cur->vm_userfaultfd_ctx.ctx =3D=3D ctx && + if (cur->vm_uffd_state.ctx =3D=3D ctx && cur->vm_flags & (VM_UFFD_WP | VM_UFFD_RWP) & ~vm_flags) goto out_unlock; =20 @@ -3985,15 +3985,15 @@ static int userfaultfd_unregister(struct userfaultf= d_ctx *ctx, do { cond_resched(); =20 - VM_WARN_ON_ONCE(!!cur->vm_userfaultfd_ctx.ctx ^ + VM_WARN_ON_ONCE(!!cur->vm_uffd_state.ctx ^ !!(cur->vm_flags & __VM_UFFD_FLAGS)); =20 /* * Prevent unregistering through a different userfaultfd than * the one used for registration. */ - if (cur->vm_userfaultfd_ctx.ctx && - cur->vm_userfaultfd_ctx.ctx !=3D ctx) + if (cur->vm_uffd_state.ctx && + cur->vm_uffd_state.ctx !=3D ctx) goto out_unlock; =20 /* @@ -4020,10 +4020,10 @@ static int userfaultfd_unregister(struct userfaultf= d_ctx *ctx, cond_resched(); =20 /* VMA not registered with userfaultfd. */ - if (!vma->vm_userfaultfd_ctx.ctx) + if (!vma->vm_uffd_state.ctx) goto skip; =20 - VM_WARN_ON_ONCE(vma->vm_userfaultfd_ctx.ctx !=3D ctx); + VM_WARN_ON_ONCE(vma->vm_uffd_state.ctx !=3D ctx); VM_WARN_ON_ONCE(!vma_can_userfault(vma, vma->vm_flags, wp_async)); VM_WARN_ON_ONCE(!(vma->vm_flags & VM_MAYWRITE)); =20 @@ -4041,7 +4041,7 @@ static int userfaultfd_unregister(struct userfaultfd_= ctx *ctx, struct userfaultfd_wake_range range; range.start =3D start; range.len =3D vma_end - start; - wake_userfault(vma->vm_userfaultfd_ctx.ctx, &range); + wake_userfault(vma->vm_uffd_state.ctx, &range); } =20 vma =3D userfaultfd_clear_vma(&vmi, prev, vma, @@ -4382,7 +4382,7 @@ static int userfaultfd_set_mode(struct userfaultfd_ct= x *ctx, VMA_ITERATOR(vmi, mm, 0); =20 for_each_vma(vmi, vma) { - if (vma->vm_userfaultfd_ctx.ctx =3D=3D ctx) + if (vma->vm_uffd_state.ctx =3D=3D ctx) vma_start_write(vma); } } @@ -4537,12 +4537,12 @@ static inline int userfaultfd_poison(struct userfau= ltfd_ctx *ctx, unsigned long =20 bool userfaultfd_wp_async(struct vm_area_struct *vma) { - return userfaultfd_wp_async_ctx(vma->vm_userfaultfd_ctx.ctx); + return userfaultfd_wp_async_ctx(vma->vm_uffd_state.ctx); } =20 bool userfaultfd_rwp_async(struct vm_area_struct *vma) { - return userfaultfd_rwp_async_ctx(vma->vm_userfaultfd_ctx.ctx); + return userfaultfd_rwp_async_ctx(vma->vm_uffd_state.ctx); } =20 static inline unsigned int uffd_ctx_features(__u64 user_features) diff --git a/mm/vma.c b/mm/vma.c index 35e7a64855fa..f2c65d148498 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -118,7 +118,7 @@ static inline bool is_mergeable_vma(struct vma_merge_st= ruct *vmg, bool merge_nex return false; if (vma->vm_file !=3D vmg->file) return false; - if (!is_mergeable_vm_userfaultfd_ctx(vma, vmg->uffd_ctx)) + if (!is_mergeable_vm_uffd_state(vma, vmg->uffd_ctx)) return false; if (!anon_vma_name_eq(anon_vma_name(vma), vmg->anon_name)) return false; @@ -1837,7 +1837,7 @@ struct vm_area_struct *vma_modify_policy(struct vma_i= terator *vmi, struct vm_area_struct *vma_modify_flags_uffd(struct vma_iterator *vmi, struct vm_area_struct *prev, struct vm_area_struct *vma, unsigned long start, unsigned long end, - const vma_flags_t *vma_flags, struct vm_userfaultfd_ctx new_ctx, + const vma_flags_t *vma_flags, struct vm_uffd_state new_ctx, bool give_up_on_oom) { VMG_VMA_STATE(vmg, vmi, prev, vma, start, end); diff --git a/mm/vma.h b/mm/vma.h index 024fabe63560..ab23a65750de 100644 --- a/mm/vma.h +++ b/mm/vma.h @@ -114,7 +114,7 @@ struct vma_merge_struct { struct file *file; struct anon_vma *anon_vma; struct mempolicy *policy; - struct vm_userfaultfd_ctx uffd_ctx; + struct vm_uffd_state uffd_ctx; struct anon_vma_name *anon_name; enum vma_merge_state state; =20 @@ -349,7 +349,7 @@ static inline void vma_sub_pgoff(struct vm_area_struct = *vma, pgoff_t delta) .file =3D vma_->vm_file, \ .anon_vma =3D vma_->anon_vma, \ .policy =3D vma_policy(vma_), \ - .uffd_ctx =3D vma_->vm_userfaultfd_ctx, \ + .uffd_ctx =3D vma_->vm_uffd_state, \ .anon_name =3D anon_vma_name(vma_), \ .state =3D VMA_MERGE_START, \ } @@ -519,7 +519,7 @@ __must_check struct vm_area_struct *vma_modify_policy(s= truct vma_iterator *vmi, __must_check struct vm_area_struct *vma_modify_flags_uffd(struct vma_itera= tor *vmi, struct vm_area_struct *prev, struct vm_area_struct *vma, unsigned long start, unsigned long end, const vma_flags_t *vma_flags, - struct vm_userfaultfd_ctx new_ctx, bool give_up_on_oom); + struct vm_uffd_state new_ctx, bool give_up_on_oom); =20 __must_check struct vm_area_struct *vma_merge_new_range(struct vma_merge_s= truct *vmg); =20 diff --git a/mm/vma_init.c b/mm/vma_init.c index baa7e82f47e3..61ddb31318bb 100644 --- a/mm/vma_init.c +++ b/mm/vma_init.c @@ -62,8 +62,8 @@ static void vm_area_init_from(const struct vm_area_struct= *src, * dup_mmap(), but the clone will reinitialize it. */ data_race(memcpy(&dest->shared, &src->shared, sizeof(dest->shared))); - memcpy(&dest->vm_userfaultfd_ctx, &src->vm_userfaultfd_ctx, - sizeof(dest->vm_userfaultfd_ctx)); + memcpy(&dest->vm_uffd_state, &src->vm_uffd_state, + sizeof(dest->vm_uffd_state)); #ifdef CONFIG_ANON_VMA_NAME dest->anon_name =3D src->anon_name; #endif diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index 4c58487b764e..1a01c3529d22 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -634,7 +634,7 @@ struct vm_area_struct { */ struct anon_vma_name *anon_name; #endif - struct vm_userfaultfd_ctx vm_userfaultfd_ctx; + struct vm_uffd_state vm_uffd_state; } __randomize_layout; =20 struct vm_operations_struct { diff --git a/tools/testing/vma/include/stubs.h b/tools/testing/vma/include/= stubs.h index d6136e19a8af..dcd1b1719928 100644 --- a/tools/testing/vma/include/stubs.h +++ b/tools/testing/vma/include/stubs.h @@ -33,7 +33,7 @@ struct unmap_desc; =20 #define ASSERT_EXCLUSIVE_WRITER(x) =20 -struct vm_userfaultfd_ctx {}; +struct vm_uffd_state {}; struct mempolicy {}; struct mmu_gather {}; struct mutex {}; @@ -350,8 +350,8 @@ static inline struct anon_vma_name *anon_vma_name(struc= t vm_area_struct *vma) return NULL; } =20 -static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *= vma, - struct vm_userfaultfd_ctx vm_ctx) +static inline bool is_mergeable_vm_uffd_state(struct vm_area_struct *vma, + struct vm_uffd_state vm_ctx) { return true; } --=20 2.53.0 From nobody Mon Sep 28 10:43:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7A603A9635; Sun, 23 Aug 2026 12:18:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487511; cv=none; b=UO8AiBE0+qMOAeZfRTLnFSSeO8+Bjty3qmRq3Cetyp5LdilDwH4SpVTxSKbxDujYp82NRrd4CgcECl5fZOQJgM84NCdry93TDWVgt/H3NbV5fess1/Jwuj1SvXKtC5sUSwgdBJifUdC0eSTcXVBQSORk8AdlyX1c0QAdf57vtFs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487511; c=relaxed/simple; bh=d1JjQ4XXueVNkbFOTpNaR+zPqDvs7mi81QObWDac/+M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jRIr60MKRxIY02cKCbJAAdWYZ0t3Durh5HmoLNWxzl/3+KkoAcv9Jkt6H5G4wbMdQ96ngWFlgVA7naCk9J1CGveSm05wcgkdJR+5LrqTc0tVS6F/WPYD9Weyo0Eo6NyWEnx6cTWiNAUIcpGm7QNEYheyHuRxqYDmO5RtppPcdoI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WDZy7SP4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WDZy7SP4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C12A1F00A3A; Sun, 23 Aug 2026 12:18:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787487509; bh=pdJ5gOM8v08CVUO0+HDRl5l80wjyOurJ8wk/kyYqYms=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=WDZy7SP4U8FmnKrmdzBNS4IzVRZNGKrq6TJUgy8UpNFk5nrYBdVxsWLZb7XwkAC1c 5t2eleHEa9td/ka+FhzA4t3opB9jRgtWijCMZWJq/ywonrI/i26mddS0fBmAGIxpL+ Gsoqlvqnvvy+bLTnzhS5pfRmmPldJe4Cj3+uc17uDtebijlX1ORivYNXgMTc06vnPJ bsKFaL0T2xsWvxIXl4nHBxFf/x1557JTyVG3imdFIIx4UTCSwMW1OL6ZmCD723vxAb 2It9j1K8H+gIGqDor1YlVX8VhAg3jxVciB/THvhHJR0dSbAZDxOqNOb7JaeeTSyO1I FRqwk95xaMfzg== From: "Mike Rapoport (Microsoft)" Date: Sun, 23 Aug 2026 15:17:42 +0300 Subject: [PATCH 5/6] userfaultfd: decouple fault reason from VMA flags Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260823-uffd-vm-flags-v1-v1-5-3086981b33cf@kernel.org> References: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> In-Reply-To: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> To: Andrew Morton , David Hildenbrand Cc: Baolin Wang , Barry Song , Dev Jain , Hugh Dickins , Jann Horn , Jason Gunthorpe , John Hubbard , Jonathan Corbet , Lance Yang , "Liam R. Howlett" , Lorenzo Stoakes , Masami Hiramatsu , Mathieu Desnoyers , Mike Rapoport , Michal Hocko , Muchun Song , Nico Pache , Oscar Salvador , Pedro Falcato , Peter Xu , Ryan Roberts , Shakeel Butt , Shuah Khan , Steven Rostedt , Suren Baghdasaryan , Usama Arif , Vlastimil Babka , Zi Yan , linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org X-Mailer: b4 0.17-dev Introduce enum uffd_reason to define reasons for user faults rather than overload VM_UFFD_* VMA flags for that. Using a dedicated enum makes the code clearer and decoupling the fault reason from VMA flags clears the way for moving the uffd mode bits out of VMA namespace. No functional change. Assisted-by: copilot:claude-opus-4.6 Signed-off-by: Mike Rapoport (Microsoft) Acked-by: Muchun Song # for HugeTLB. --- include/linux/userfaultfd_k.h | 16 ++++++++++++++-- include/uapi/linux/userfaultfd.h | 6 +++--- mm/huge_memory.c | 6 +++--- mm/hugetlb.c | 10 +++++----- mm/memory.c | 10 +++++----- mm/shmem.c | 4 ++-- mm/userfaultfd.c | 30 +++++++++++++++--------------- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index 45355bdb4ec7..f401623f315d 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -9,6 +9,18 @@ #ifndef _LINUX_USERFAULTFD_K_H #define _LINUX_USERFAULTFD_K_H =20 +#include + +/* Fault reason #PF handler passes to handle_userfault() */ +enum uf_reason { + USERFAULT_MISSING =3D BIT(0), + USERFAULT_MINOR =3D BIT(1), + USERFAULT_RWP =3D BIT(2), + USERFAULT_WP =3D BIT(3), +}; +#define USERFAULT_ANY (USERFAULT_MISSING | USERFAULT_MINOR | \ + USERFAULT_RWP | USERFAULT_WP) + #ifdef CONFIG_USERFAULTFD =20 #include /* linux/include/uapi/linux/userfaultfd.h */ @@ -82,7 +94,7 @@ struct userfaultfd_ctx { struct mm_struct *mm; }; =20 -extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long rea= son); +vm_fault_t handle_userfault(struct vm_fault *vmf, enum uf_reason reason); =20 /* VMA userfaultfd operations */ struct vm_uffd_ops { @@ -333,7 +345,7 @@ static inline bool pte_swp_uffd_any(pte_t pte) =20 /* mm helpers */ static inline vm_fault_t handle_userfault(struct vm_fault *vmf, - unsigned long reason) + enum uf_reason reason) { return VM_FAULT_SIGBUS; } diff --git a/include/uapi/linux/userfaultfd.h b/include/uapi/linux/userfaul= tfd.h index cea11aad6b54..ed2c42d427b9 100644 --- a/include/uapi/linux/userfaultfd.h +++ b/include/uapi/linux/userfaultfd.h @@ -168,9 +168,9 @@ struct uffd_msg { =20 /* flags for UFFD_EVENT_PAGEFAULT */ #define UFFD_PAGEFAULT_FLAG_WRITE (1<<0) /* If this was a write fault */ -#define UFFD_PAGEFAULT_FLAG_WP (1<<1) /* If reason is VM_UFFD_WP */ -#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2) /* If reason is VM_UFFD_MINOR */ -#define UFFD_PAGEFAULT_FLAG_RWP (1<<3) /* If reason is VM_UFFD_RWP */ +#define UFFD_PAGEFAULT_FLAG_WP (1<<1) /* If reason is uffd-wp */ +#define UFFD_PAGEFAULT_FLAG_MINOR (1<<2) /* If reason is uffd-minor */ +#define UFFD_PAGEFAULT_FLAG_RWP (1<<3) /* If reason is uffd-rwp */ =20 struct uffdio_api { /* userland asks for an API number and the features to enable */ diff --git a/mm/huge_memory.c b/mm/huge_memory.c index ced400f72d43..46d8497ce90e 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1410,7 +1410,7 @@ static vm_fault_t __do_huge_pmd_anonymous_page(struct= vm_fault *vmf) spin_unlock(vmf->ptl); folio_put(folio); pte_free(vma->vm_mm, pgtable); - ret =3D handle_userfault(vmf, VM_UFFD_MISSING); + ret =3D handle_userfault(vmf, USERFAULT_MISSING); VM_BUG_ON(ret & VM_FAULT_FALLBACK); return ret; } @@ -1556,7 +1556,7 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault= *vmf) } else if (userfaultfd_missing(vma)) { spin_unlock(vmf->ptl); pte_free(vma->vm_mm, pgtable); - ret =3D handle_userfault(vmf, VM_UFFD_MISSING); + ret =3D handle_userfault(vmf, USERFAULT_MISSING); VM_BUG_ON(ret & VM_FAULT_FALLBACK); } else { set_huge_zero_folio(pgtable, vma->vm_mm, vma, @@ -2252,7 +2252,7 @@ vm_fault_t do_huge_pmd_uffd_rwp(struct vm_fault *vmf) pmd_t pmd; =20 if (!userfaultfd_rwp_async(vma)) - return handle_userfault(vmf, VM_UFFD_RWP); + return handle_userfault(vmf, USERFAULT_RWP); =20 vmf->ptl =3D pmd_lock(vma->vm_mm, vmf->pmd); if (unlikely(!pmd_same(pmdp_get(vmf->pmd), vmf->orig_pmd))) { diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 73d65644be13..5e2ed80c1938 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -5728,7 +5728,7 @@ int hugetlb_add_to_page_cache(struct folio *folio, st= ruct address_space *mapping =20 static inline vm_fault_t hugetlb_handle_userfault(struct vm_fault *vmf, struct address_space *mapping, - unsigned long reason) + enum uf_reason reason) { u32 hash; =20 @@ -5821,7 +5821,7 @@ static vm_fault_t hugetlb_no_page(struct address_spac= e *mapping, } =20 return hugetlb_handle_userfault(vmf, mapping, - VM_UFFD_MISSING); + USERFAULT_MISSING); } =20 if (!(vma->vm_flags & VM_MAYSHARE)) { @@ -5897,7 +5897,7 @@ static vm_fault_t hugetlb_no_page(struct address_spac= e *mapping, goto out; } return hugetlb_handle_userfault(vmf, mapping, - VM_UFFD_MINOR); + USERFAULT_MINOR); } } =20 @@ -6120,7 +6120,7 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct= vm_area_struct *vma, =20 /* Sync: drop hugetlb locks before blocking in handle_userfault() */ if (!userfaultfd_rwp_async(vma)) - return hugetlb_handle_userfault(&vmf, mapping, VM_UFFD_RWP); + return hugetlb_handle_userfault(&vmf, mapping, USERFAULT_RWP); =20 ptl =3D huge_pte_lock(h, mm, vmf.pte); pte =3D huge_ptep_get(mm, vmf.address, vmf.pte); @@ -6177,7 +6177,7 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct= vm_area_struct *vma, spin_unlock(vmf.ptl); hugetlb_vma_unlock_read(vma); mutex_unlock(&hugetlb_fault_mutex_table[hash]); - return handle_userfault(&vmf, VM_UFFD_WP); + return handle_userfault(&vmf, USERFAULT_WP); } =20 vmf.orig_pte =3D huge_pte_clear_uffd(vmf.orig_pte); diff --git a/mm/memory.c b/mm/memory.c index c54943302553..1a9b41704b0c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4389,7 +4389,7 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf) if (userfaultfd_pte_wp(vma, ptep_get(vmf->pte))) { if (!userfaultfd_wp_async(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); - return handle_userfault(vmf, VM_UFFD_WP); + return handle_userfault(vmf, USERFAULT_WP); } =20 /* @@ -5463,7 +5463,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *= vmf) /* Deliver the page fault to userland, check inside PT lock */ if (userfaultfd_missing(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); - return handle_userfault(vmf, VM_UFFD_MISSING); + return handle_userfault(vmf, USERFAULT_MISSING); } if (vmf_orig_pte_uffd_wp(vmf)) entry =3D pte_mkuffd(entry); @@ -5514,7 +5514,7 @@ static vm_fault_t do_anonymous_page(struct vm_fault *= vmf) if (userfaultfd_missing(vma)) { pte_unmap_unlock(vmf->pte, vmf->ptl); folio_put(folio); - return handle_userfault(vmf, VM_UFFD_MISSING); + return handle_userfault(vmf, USERFAULT_MISSING); } map_anon_folio_pte_pf(folio, vmf->pte, vma, addr, vmf_orig_pte_uffd_wp(vmf)); @@ -6263,7 +6263,7 @@ static vm_fault_t do_uffd_rwp(struct vm_fault *vmf) if (!userfaultfd_rwp_async(vmf->vma)) { /* Sync mode: unmap PTE and deliver to userfaultfd handler */ pte_unmap(vmf->pte); - return handle_userfault(vmf, VM_UFFD_RWP); + return handle_userfault(vmf, USERFAULT_RWP); } =20 spin_lock(vmf->ptl); @@ -6398,7 +6398,7 @@ static inline vm_fault_t wp_huge_pmd(struct vm_fault = *vmf) userfaultfd_huge_pmd_wp(vma, vmf->orig_pmd)) { if (userfaultfd_wp_async(vmf->vma)) goto split; - return handle_userfault(vmf, VM_UFFD_WP); + return handle_userfault(vmf, USERFAULT_WP); } return do_huge_pmd_wp_page(vmf); } diff --git a/mm/shmem.c b/mm/shmem.c index 599665a3d6e7..2138a4e6b549 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2453,7 +2453,7 @@ static int shmem_get_folio_gfp(struct inode *inode, p= goff_t index, if (folio && vma && userfaultfd_minor(vma)) { if (!xa_is_value(folio)) folio_put(folio); - *fault_type =3D handle_userfault(vmf, VM_UFFD_MINOR); + *fault_type =3D handle_userfault(vmf, USERFAULT_MINOR); return 0; } =20 @@ -2502,7 +2502,7 @@ static int shmem_get_folio_gfp(struct inode *inode, p= goff_t index, */ =20 if (vma && userfaultfd_missing(vma)) { - *fault_type =3D handle_userfault(vmf, VM_UFFD_MISSING); + *fault_type =3D handle_userfault(vmf, USERFAULT_MISSING); return 0; } =20 diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 119304547230..83587d34b189 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -2607,7 +2607,7 @@ static inline void msg_init(struct uffd_msg *msg) static inline struct uffd_msg userfault_msg(unsigned long address, unsigned long real_address, unsigned int flags, - unsigned long reason, + enum uf_reason reason, unsigned int features) { struct uffd_msg msg; @@ -2629,11 +2629,11 @@ static inline struct uffd_msg userfault_msg(unsigne= d long address, */ if (flags & FAULT_FLAG_WRITE) msg.arg.pagefault.flags |=3D UFFD_PAGEFAULT_FLAG_WRITE; - if (reason & VM_UFFD_WP) + if (reason & USERFAULT_WP) msg.arg.pagefault.flags |=3D UFFD_PAGEFAULT_FLAG_WP; - if (reason & VM_UFFD_RWP) + if (reason & USERFAULT_RWP) msg.arg.pagefault.flags |=3D UFFD_PAGEFAULT_FLAG_RWP; - if (reason & VM_UFFD_MINOR) + if (reason & USERFAULT_MINOR) msg.arg.pagefault.flags |=3D UFFD_PAGEFAULT_FLAG_MINOR; if (features & UFFD_FEATURE_THREAD_ID) msg.arg.pagefault.feat.ptid =3D task_pid_vnr(current); @@ -2647,7 +2647,7 @@ static inline struct uffd_msg userfault_msg(unsigned = long address, */ static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, struct vm_fault *vmf, - unsigned long reason) + enum uf_reason reason) { struct vm_area_struct *vma =3D vmf->vma; pte_t *ptep, pte; @@ -2684,13 +2684,13 @@ static inline bool userfaultfd_huge_must_wait(struc= t userfaultfd_ctx *ctx, * If VMA has UFFD WP faults enabled and WP fault, wait for userspace to * resolve the fault. */ - if (!huge_pte_write(pte) && (reason & VM_UFFD_WP)) + if (!huge_pte_write(pte) && (reason & USERFAULT_WP)) return true; /* * PTE is still RW-protected (protnone with uffd bit), wait for * resolution. Plain PROT_NONE without the marker is not an RWP fault. */ - if (pte_protnone(pte) && huge_pte_uffd(pte) && (reason & VM_UFFD_RWP)) + if (pte_protnone(pte) && huge_pte_uffd(pte) && (reason & USERFAULT_RWP)) return true; =20 return false; @@ -2698,7 +2698,7 @@ static inline bool userfaultfd_huge_must_wait(struct = userfaultfd_ctx *ctx, #else static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx, struct vm_fault *vmf, - unsigned long reason) + enum uf_reason reason) { /* Should never get here. */ VM_WARN_ON_ONCE(1); @@ -2715,7 +2715,7 @@ static inline bool userfaultfd_huge_must_wait(struct = userfaultfd_ctx *ctx, */ static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx, struct vm_fault *vmf, - unsigned long reason) + enum uf_reason reason) { struct mm_struct *mm =3D ctx->mm; unsigned long address =3D vmf->address; @@ -2753,10 +2753,10 @@ static inline bool userfaultfd_must_wait(struct use= rfaultfd_ctx *ctx, return false; =20 if (pmd_trans_huge(_pmd)) { - if (!pmd_write(_pmd) && (reason & VM_UFFD_WP)) + if (!pmd_write(_pmd) && (reason & USERFAULT_WP)) return true; if (pmd_protnone(_pmd) && pmd_uffd(_pmd) && - (reason & VM_UFFD_RWP)) + (reason & USERFAULT_RWP)) return true; return false; } @@ -2793,14 +2793,14 @@ static inline bool userfaultfd_must_wait(struct use= rfaultfd_ctx *ctx, * If VMA has UFFD WP faults enabled and WP fault, wait for userspace to * resolve the fault. */ - if (!pte_write(ptent) && (reason & VM_UFFD_WP)) + if (!pte_write(ptent) && (reason & USERFAULT_WP)) goto out; /* * PTE is still RW-protected (protnone with uffd bit), wait for * userspace to resolve. Plain PROT_NONE without the marker is not * an RWP fault. */ - if (pte_protnone(ptent) && pte_uffd(ptent) && (reason & VM_UFFD_RWP)) + if (pte_protnone(ptent) && pte_uffd(ptent) && (reason & USERFAULT_RWP)) goto out; =20 ret =3D false; @@ -2835,7 +2835,7 @@ static inline unsigned int userfaultfd_get_blocking_s= tate(unsigned int flags) * fatal_signal_pending()s, and the mmap_lock must be released before * returning it. */ -vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason) +vm_fault_t handle_userfault(struct vm_fault *vmf, enum uf_reason reason) { struct vm_area_struct *vma =3D vmf->vma; struct mm_struct *mm =3D vma->vm_mm; @@ -2861,7 +2861,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, uns= igned long reason) VM_WARN_ON_ONCE(ctx->mm !=3D mm); =20 /* Any unrecognized flag is a bug. */ - VM_WARN_ON_ONCE(reason & ~__VM_UFFD_FLAGS); + VM_WARN_ON_ONCE(reason & ~USERFAULT_ANY); /* 0 or > 1 flags set is a bug; we expect exactly 1. */ VM_WARN_ON_ONCE(!reason || (reason & (reason - 1))); =20 --=20 2.53.0 From nobody Mon Sep 28 10:43:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A562361DBF; Sun, 23 Aug 2026 12:18:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487520; cv=none; b=bEnlLTFnozo5hqgin6BWOzJV/kX20mzsEemQWl19u5ERVmxqNaG6ldOYE4+4zJNqV+0k+K3QsU6dNlAnNt0lkvcvQsq7KztsxxttWsLJGUynPZvlDR40AbTQdgbsiYTeATeyg0VjovU5j8943LToFByOj/7yu1LhOua3MUrbn3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787487520; c=relaxed/simple; bh=ZEHeJtVaViYkn//74ca9ORjlFe5yNEbCH0/QLa6EgFg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OB9i+c4EDyVIuEmm0+wpyUCzyyGHmGZDW/ZRPP6J9m3GZfm1KREdzPvbDnTgvtJ5AnvozqopFV7s5tHj9vYKU9lD4MNdGtaAcu02Zh85Hgyo8D0UqapwaTu/gfLtxjSODJQqNOAlFfDXt4XYzObVux11OCPN04C+4M/GbzCjPeM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jEeO1asY; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jEeO1asY" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 565101F000E9; Sun, 23 Aug 2026 12:18:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1787487517; bh=yyND48Jk/AUcTHnSp2xhU1NTg8Gmmq5Xfa7qwMCpYtA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=jEeO1asYSvT4efCXf5aTF5QggakbkAutPEVTUqQzVGJXJ6VwooIUl5pYIXTZEaRgV JtzYsUh0p9QMqn12iE2iNDuQQlUgHdGRVHhMS4dUp9MOu3tahjKh4O3tL5VxTUCyg2 cC0+L+Dxb97bPTcYzx5Xv81nN6qexeQxoSyq+mE0fuThXZqbIEfxyzGxjCP/GdB3eL U5BgpdqAULVLCgsT0HRAw95qytPIR+uqnVtRolrZY02TnS3hNxdEKwhOhJam9+UlcB 9Cx9aQelCSgfIoliHwJaroDkH1yxVqTcI4GGjKY9yAk1WCeiiWHFv1EH1zh+ny1/iS KzSLfzWU5769Q== From: "Mike Rapoport (Microsoft)" Date: Sun, 23 Aug 2026 15:17:43 +0300 Subject: [PATCH 6/6] userfaultfd: collapse VM_UFFD_{MISSING,WP,MINOR,RWP} into single VM_UFFD Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260823-uffd-vm-flags-v1-v1-6-3086981b33cf@kernel.org> References: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> In-Reply-To: <20260823-uffd-vm-flags-v1-v1-0-3086981b33cf@kernel.org> To: Andrew Morton , David Hildenbrand Cc: Baolin Wang , Barry Song , Dev Jain , Hugh Dickins , Jann Horn , Jason Gunthorpe , John Hubbard , Jonathan Corbet , Lance Yang , "Liam R. Howlett" , Lorenzo Stoakes , Masami Hiramatsu , Mathieu Desnoyers , Mike Rapoport , Michal Hocko , Muchun Song , Nico Pache , Oscar Salvador , Pedro Falcato , Peter Xu , Ryan Roberts , Shakeel Butt , Shuah Khan , Steven Rostedt , Suren Baghdasaryan , Usama Arif , Vlastimil Babka , Zi Yan , linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-trace-kernel@vger.kernel.org X-Mailer: b4 0.17-dev Add 'mode' field to struct vm_uffd_state and define UFFD_MODE_ flags. Use this field to differentiate VMA registration with userfaultfd instead of relying on VM_UFFD_* flags. A VMA registered with userfaultfd will have a single VM_UFFD flag set and its registration mode (MISSING, MINOR, WP, RWP) is determined by vm_uffd_state.mode. This frees three vm_flags bits (12, 41, 43). Update the relevant code to use UFFD_MODE_* instead of VM_UFFD_* flags. Remove VM_UFFD_WP and VM_UFFD_RWP from VM_COPY_ON_FORK, adding an explicit userfaultfd_protected() check in vma_needs_copy() instead. /proc/pid/smaps representation of VmFlags is slightly changed: - any VMA registered with UFFD shows 'uf' - the existing userfault markers ('um', 'uw', 'ui', 'ur') are shown after VmFlags rather than in the middle Assisted-by: copilot:claude-opus-4.6 Signed-off-by: Mike Rapoport (Microsoft) --- fs/proc/task_mmu.c | 18 +++--- include/linux/mm.h | 67 +++++----------------- include/linux/mm_types.h | 1 + include/linux/pgtable.h | 4 +- include/linux/userfaultfd_k.h | 37 +++++++----- include/trace/events/mmflags.h | 17 +----- mm/gup.c | 5 +- mm/hugetlb.c | 2 +- mm/khugepaged.c | 2 +- mm/memory.c | 6 +- mm/mprotect.c | 2 +- mm/shmem.c | 2 +- mm/userfaultfd.c | 123 +++++++++++++++++++++---------------= ---- tools/testing/vma/include/dup.h | 18 ++---- 14 files changed, 134 insertions(+), 170 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 5c54aebe2118..8d344c6ee14e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -23,6 +23,7 @@ #include #include #include +#include =20 #include #include @@ -1216,8 +1217,7 @@ static void show_smap_vma_flags(struct seq_file *m, s= truct vm_area_struct *vma) [ilog2(VM_HUGEPAGE)] =3D "hg", [ilog2(VM_NOHUGEPAGE)] =3D "nh", [ilog2(VM_MERGEABLE)] =3D "mg", - [ilog2(VM_UFFD_MISSING)]=3D "um", - [ilog2(VM_UFFD_WP)] =3D "uw", + [ilog2(VM_UFFD)] =3D "uf", #ifdef CONFIG_ARM64_MTE [ilog2(VM_MTE)] =3D "mt", [ilog2(VM_MTE_ALLOWED)] =3D "", @@ -1234,12 +1234,6 @@ static void show_smap_vma_flags(struct seq_file *m, = struct vm_area_struct *vma) [ilog2(VM_PKEY_BIT4)] =3D "", #endif #endif /* CONFIG_ARCH_HAS_PKEYS */ -#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR - [ilog2(VM_UFFD_MINOR)] =3D "ui", -#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_MINOR */ -#ifdef CONFIG_USERFAULTFD_RWP - [ilog2(VM_UFFD_RWP)] =3D "ur", -#endif #ifdef CONFIG_ARCH_HAS_USER_SHADOW_STACK [ilog2(VM_SHADOW_STACK)] =3D "ss", #endif @@ -1259,6 +1253,14 @@ static void show_smap_vma_flags(struct seq_file *m, = struct vm_area_struct *vma) if (vma->vm_flags & (1UL << i)) seq_printf(m, "%s ", mnemonics[i]); } + if (userfaultfd_missing(vma)) + seq_puts(m, "um "); + if (userfaultfd_wp(vma)) + seq_puts(m, "uw "); + if (userfaultfd_minor(vma)) + seq_puts(m, "ui "); + if (userfaultfd_rwp(vma)) + seq_puts(m, "ur "); seq_putc(m, '\n'); } =20 diff --git a/include/linux/mm.h b/include/linux/mm.h index 4daf9cd6ae8e..416de7663951 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -303,7 +303,7 @@ enum { DECLARE_VMA_BIT(MAYSHARE, 7), DECLARE_VMA_BIT(GROWSDOWN, 8), /* general info on the segment */ #ifdef CONFIG_MMU - DECLARE_VMA_BIT(UFFD_MISSING, 9),/* missing pages tracking */ + DECLARE_VMA_BIT(UFFD, 9), /* userfaultfd registered */ #else /* nommu: R/O MAP_PRIVATE mapping that might overlay a file mapping */ DECLARE_VMA_BIT(MAYOVERLAY, 9), @@ -311,7 +311,7 @@ enum { /* Page-ranges managed without "struct page", just pure PFN */ DECLARE_VMA_BIT(PFNMAP, 10), DECLARE_VMA_BIT(MAYBE_GUARD, 11), - DECLARE_VMA_BIT(UFFD_WP, 12), /* wrprotect pages tracking */ + /* Bit 12 is free */ DECLARE_VMA_BIT(LOCKED, 13), DECLARE_VMA_BIT(IO, 14), /* Memory mapped I/O or similar */ DECLARE_VMA_BIT(SEQ_READ, 15), /* App will access data sequentially */ @@ -352,9 +352,8 @@ enum { #elif defined(CONFIG_64BIT) DECLARE_VMA_BIT(DROPPABLE, 40), #endif - DECLARE_VMA_BIT(UFFD_MINOR, 41), + /* Bits 41 and 43 are free */ DECLARE_VMA_BIT(SEALED, 42), - DECLARE_VMA_BIT(UFFD_RWP, 43), /* Flags that reuse flags above. */ DECLARE_VMA_BIT_ALIAS(PKEY_BIT0, HIGH_ARCH_0), DECLARE_VMA_BIT_ALIAS(PKEY_BIT1, HIGH_ARCH_1), @@ -408,14 +407,14 @@ enum { #define VM_MAYSHARE INIT_VM_FLAG(MAYSHARE) #define VM_GROWSDOWN INIT_VM_FLAG(GROWSDOWN) #ifdef CONFIG_MMU -#define VM_UFFD_MISSING INIT_VM_FLAG(UFFD_MISSING) +#define VM_UFFD INIT_VM_FLAG(UFFD) +#define VMA_UFFD mk_vma_flags(VMA_UFFD_BIT) #else -#define VM_UFFD_MISSING VM_NONE +#define VM_UFFD VM_NONE #define VM_MAYOVERLAY INIT_VM_FLAG(MAYOVERLAY) #endif #define VM_PFNMAP INIT_VM_FLAG(PFNMAP) #define VM_MAYBE_GUARD INIT_VM_FLAG(MAYBE_GUARD) -#define VM_UFFD_WP INIT_VM_FLAG(UFFD_WP) #define VM_LOCKED INIT_VM_FLAG(LOCKED) #define VM_IO INIT_VM_FLAG(IO) #define VM_SEQ_READ INIT_VM_FLAG(SEQ_READ) @@ -499,36 +498,6 @@ enum { #define VM_MTE VM_NONE #define VM_MTE_ALLOWED VM_NONE #endif -#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR -#define VM_UFFD_MINOR INIT_VM_FLAG(UFFD_MINOR) -#else -#define VM_UFFD_MINOR VM_NONE -#endif -#ifdef CONFIG_USERFAULTFD_RWP -#define VM_UFFD_RWP INIT_VM_FLAG(UFFD_RWP) -#else -#define VM_UFFD_RWP VM_NONE -#endif - -/* - * vma_flags_t masks for the userfaultfd VMA flags. The two high-bit modes= are - * gated on the same configs as their VM_* flags above -- both of which im= ply - * 64BIT -- so an out-of-range bit is never fed to mk_vma_flags() on a bui= ld - * whose bitmap cannot hold it. - */ -#define VMA_UFFD_MISSING mk_vma_flags(VMA_UFFD_MISSING_BIT) -#define VMA_UFFD_WP mk_vma_flags(VMA_UFFD_WP_BIT) -#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR -#define VMA_UFFD_MINOR mk_vma_flags(VMA_UFFD_MINOR_BIT) -#else -#define VMA_UFFD_MINOR EMPTY_VMA_FLAGS -#endif -#ifdef CONFIG_USERFAULTFD_RWP -#define VMA_UFFD_RWP mk_vma_flags(VMA_UFFD_RWP_BIT) -#else -#define VMA_UFFD_RWP EMPTY_VMA_FLAGS -#endif - #ifdef CONFIG_64BIT #define VM_ALLOW_ANY_UNCACHED INIT_VM_FLAG(ALLOW_ANY_UNCACHED) #define VM_SEALED INIT_VM_FLAG(SEALED) @@ -668,32 +637,26 @@ enum { * reconsistuted upon page fault, so necessitate page table copying upon f= ork. * * Note that these flags should be compared with the DESTINATION VMA not t= he - * source: VM_UFFD_WP and VM_UFFD_RWP may be cleared on the destination + * source: uffd WP/RWP mode may be cleared on the destination * (dup_userfaultfd() -> userfaultfd_reset_ctx() when the parent context d= id * not negotiate UFFD_FEATURE_EVENT_FORK), while all other flags propagate. * * VM_PFNMAP / VM_MIXEDMAP - These contain kernel-mapped data which cannot= be * reasonably reconstructed on page fault. * - * VM_UFFD_WP - Encodes metadata about an installed uffd - * VM_UFFD_RWP write- or read-write-protect handler, which - * cannot be reconstructed on page fault. - * - * We always copy pgtables when dst_vma has the - * uffd PTE bit in use even if it's file-backed - * (e.g. shmem). Because when the uffd bit is - * in use, the pgtable contains the protection - * information, that's something we can't - * retrieve from page cache, and skip copying - * will lose those info. - * * VM_MAYBE_GUARD - Could contain page guard region markers which * by design are a property of the page tables * only and thus cannot be reconstructed on page * fault. + * + * uffd WP/RWP modes - Encode metadata about an installed uffd + * write- or read-write-protect handler, which + * cannot be reconstructed on page fault. + * This is checked separately via + * userfaultfd_protected() in vma_needs_copy(). + * */ -#define VM_COPY_ON_FORK (VM_PFNMAP | VM_MIXEDMAP | VM_UFFD_WP | VM_UFFD_RW= P | \ - VM_MAYBE_GUARD) +#define VM_COPY_ON_FORK (VM_PFNMAP | VM_MIXEDMAP | VM_MAYBE_GUARD) =20 /* * mapping from the currently active vm_flags protection bits (the diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index d6deb655d82e..8354d1c18b29 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -723,6 +723,7 @@ struct vm_region { #define NULL_VM_UFFD_STATE ((struct vm_uffd_state) { NULL, }) struct vm_uffd_state { struct userfaultfd_ctx *ctx; + unsigned int mode; }; #else /* CONFIG_USERFAULTFD */ #define NULL_VM_UFFD_STATE ((struct vm_uffd_state) {}) diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index 8c093c119e5a..4b74c298cc14 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h @@ -2119,8 +2119,8 @@ static inline int pud_trans_unstable(pud_t *pud) * In an accessible VMA, pte_protnone() reliably indicates a present * PROT_NONE page protection. Today the kernel uses such PTEs for two * purposes: NUMA hinting faults, and userfaultfd RWP tracking on - * VM_UFFD_RWP VMAs. The two are distinguished by the uffd PTE bit and - * the VMA flag; see include/linux/userfaultfd_k.h. + * uffd-RWP VMAs. The two are distinguished by the uffd PTE bit and + * the VMA uffd state; see include/linux/userfaultfd_k.h. * * So, to reliably identify PROT_NONE PTEs that require kernel handling, * looking at the VMA accessibility (and the uffd bit on RWP VMAs) is diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index f401623f315d..b4261038d10a 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -32,12 +32,13 @@ enum uf_reason { #include #include =20 -/* The set of all possible UFFD-related VM flags. */ -#define __VM_UFFD_FLAGS (VM_UFFD_MISSING | VM_UFFD_MINOR | \ - VM_UFFD_WP | VM_UFFD_RWP) - -#define __VMA_UFFD_FLAGS mk_vma_flags_from_masks(VMA_UFFD_MISSING, VMA_UFF= D_WP, \ - VMA_UFFD_MINOR, VMA_UFFD_RWP) +/* Per-VMA uffd modes */ +#define UFFD_MODE_MISSING BIT(0) +#define UFFD_MODE_MINOR BIT(1) +#define UFFD_MODE_RWP BIT(2) +#define UFFD_MODE_WP BIT(3) +#define UFFD_MODE_ALL (UFFD_MODE_MISSING | UFFD_MODE_MINOR | \ + UFFD_MODE_RWP | UFFD_MODE_WP) =20 /* * CAREFUL: Check include/uapi/asm-generic/fcntl.h when defining @@ -99,7 +100,7 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, enum u= f_reason reason); /* VMA userfaultfd operations */ struct vm_uffd_ops { /* Checks if a VMA can support userfaultfd */ - bool (*can_userfault)(struct vm_area_struct *vma, vm_flags_t vm_flags); + bool (*can_userfault)(struct vm_area_struct *vma, unsigned int mode); /* * Called to resolve UFFDIO_CONTINUE request. * Should return the folio found at pgoff in the VMA's pagecache if it @@ -174,25 +175,34 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *= dst_pmd, pmd_t *src_pmd, pm unsigned long dst_addr, unsigned long src_addr); =20 /* mm helpers */ +static inline unsigned int uffd_mode(const struct vm_area_struct *vma) +{ + return vma->vm_uffd_state.mode; +} + static inline bool is_mergeable_vm_uffd_state(struct vm_area_struct *vma, struct vm_uffd_state vm_ctx) { - return vma->vm_uffd_state.ctx =3D=3D vm_ctx.ctx; + return vma->vm_uffd_state.ctx =3D=3D vm_ctx.ctx && + uffd_mode(vma) =3D=3D vm_ctx.mode; } =20 static inline bool userfaultfd_missing(const struct vm_area_struct *vma) { - return vma_test_any_mask(vma, VMA_UFFD_MISSING); + return vma_test(vma, VMA_UFFD_BIT) && + (uffd_mode(vma) & UFFD_MODE_MISSING); } =20 static inline bool userfaultfd_wp(const struct vm_area_struct *vma) { - return vma_test_any_mask(vma, VMA_UFFD_WP); + return vma_test(vma, VMA_UFFD_BIT) && + (uffd_mode(vma) & UFFD_MODE_WP); } =20 static inline bool userfaultfd_minor(const struct vm_area_struct *vma) { - return vma_test_any_mask(vma, VMA_UFFD_MINOR); + return vma_test(vma, VMA_UFFD_BIT) && + (uffd_mode(vma) & UFFD_MODE_MINOR); } =20 static inline bool userfaultfd_rwp(const struct vm_area_struct *vma) @@ -203,7 +213,8 @@ static inline bool userfaultfd_rwp(const struct vm_area= _struct *vma) */ if (!IS_ENABLED(CONFIG_ARCH_HAS_PTE_PROTNONE)) return false; - return vma_test_single_mask(vma, VMA_UFFD_RWP); + return vma_test(vma, VMA_UFFD_BIT) && + (uffd_mode(vma) & UFFD_MODE_RWP); } =20 static inline bool userfaultfd_protected(const struct vm_area_struct *vma) @@ -271,7 +282,7 @@ static inline bool userfaultfd_huge_pmd_rwp(struct vm_a= rea_struct *vma, =20 static inline bool userfaultfd_armed(struct vm_area_struct *vma) { - return vma_test_any_mask(vma, __VMA_UFFD_FLAGS); + return vma_test(vma, VMA_UFFD_BIT); } =20 static inline bool vma_has_uffd_without_event_remap(struct vm_area_struct = *vma) diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h index 935893e5ea53..aacdd90e0a64 100644 --- a/include/trace/events/mmflags.h +++ b/include/trace/events/mmflags.h @@ -180,18 +180,6 @@ IF_HAVE_PG_ARCH_3(arch_3) #define IF_HAVE_VM_SOFTDIRTY(flag,name) #endif =20 -#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR -# define IF_HAVE_UFFD_MINOR(flag, name) {flag, name}, -#else -# define IF_HAVE_UFFD_MINOR(flag, name) -#endif - -#ifdef CONFIG_USERFAULTFD_RWP -# define IF_HAVE_UFFD_RWP(flag, name) {flag, name}, -#else -# define IF_HAVE_UFFD_RWP(flag, name) -#endif - #if defined(CONFIG_64BIT) || defined(CONFIG_PPC32) # define IF_HAVE_VM_DROPPABLE(flag, name) {flag, name}, #else @@ -208,12 +196,9 @@ IF_HAVE_PG_ARCH_3(arch_3) {VM_MAYEXEC, "mayexec" }, \ {VM_MAYSHARE, "mayshare" }, \ {VM_GROWSDOWN, "growsdown" }, \ - {VM_UFFD_MISSING, "uffd_missing" }, \ -IF_HAVE_UFFD_MINOR(VM_UFFD_MINOR, "uffd_minor" ) \ + {VM_UFFD, "uffd" }, \ {VM_PFNMAP, "pfnmap" }, \ {VM_MAYBE_GUARD, "maybe_guard" }, \ - {VM_UFFD_WP, "uffd_wp" }, \ -IF_HAVE_UFFD_RWP(VM_UFFD_RWP, "uffd_rwp" ) \ {VM_LOCKED, "locked" }, \ {VM_IO, "io" }, \ {VM_SEQ_READ, "seqread" }, \ diff --git a/mm/gup.c b/mm/gup.c index 500e2aa99e48..9243c41a0c0e 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -12,6 +12,7 @@ #include #include #include +#include =20 #include #include @@ -641,7 +642,7 @@ static inline bool gup_can_follow_protnone(const struct= vm_area_struct *vma, unsigned int flags) { /* - * VM_UFFD_RWP uses protnone as an access-tracking marker, not for + * uffd-RWP uses protnone as an access-tracking marker, not for * NUMA hinting. GUP must always take a fault so the access is * delivered to userfaultfd, regardless of FOLL_HONOR_NUMA_FAULT. * @@ -651,7 +652,7 @@ static inline bool gup_can_follow_protnone(const struct= vm_area_struct *vma, * no progress on protnone in an inaccessible VMA, and the access is * denied regardless of RWP anyway. */ - if (vma_test_single_mask(vma, VMA_UFFD_RWP) && vma_is_accessible(vma)) + if (userfaultfd_rwp(vma) && vma_is_accessible(vma)) return false; =20 /* diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 5e2ed80c1938..a15c443474d5 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4808,7 +4808,7 @@ static vm_fault_t hugetlb_vm_op_fault(struct vm_fault= *vmf) =20 #ifdef CONFIG_USERFAULTFD static bool hugetlb_can_userfault(struct vm_area_struct *vma, - vm_flags_t vm_flags) + unsigned int mode) { return true; } diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 79effd3f3da4..7f590a1d3ca3 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -2112,7 +2112,7 @@ static bool file_backed_vma_is_retractable(struct vm_= area_struct *vma) /* * When a vma is registered with uffd-wp or RWP, we cannot recycle * the page table because there may be pte markers installed. - * VM_UFFD_RWP ranges similarly rely on per-PTE uffd state + * uffd-RWP ranges similarly rely on per-PTE uffd state * and cannot be recycled to a shared PMD. Other vmas can still * have the same file mapped hugely, but skip this one: it will * always be mapped in small page size for these registrations. diff --git a/mm/memory.c b/mm/memory.c index 1a9b41704b0c..c12ec979199c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1565,10 +1565,12 @@ vma_needs_copy(struct vm_area_struct *dst_vma, stru= ct vm_area_struct *src_vma) { /* * We check against dst_vma as while sane VMA flags will have been - * copied, VM_UFFD_WP may be set only on dst_vma. + * copied, userfaultfd WP/RWP mode may be set only on dst_vma. */ if (dst_vma->vm_flags & VM_COPY_ON_FORK) return true; + if (userfaultfd_protected(dst_vma)) + return true; /* * The presence of an anon_vma indicates an anonymous VMA has page * tables which naturally cannot be reconstituted on page fault. @@ -6563,7 +6565,7 @@ static vm_fault_t handle_pte_fault(struct vm_fault *v= mf) if (pte_protnone(vmf->orig_pte) && vma_is_accessible(vmf->vma)) { /* * RWP-protected PTEs are protnone plus the uffd bit. On a - * VM_UFFD_RWP VMA, a protnone PTE without the uffd bit is + * uffd-RWP VMA, a protnone PTE without the uffd bit is * NUMA hinting and must still fall through to do_numa_page(). */ if (userfaultfd_pte_rwp(vmf->vma, vmf->orig_pte)) diff --git a/mm/mprotect.c b/mm/mprotect.c index 2888ee638d87..b98d4372677b 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -297,7 +297,7 @@ static __always_inline void change_present_ptes(struct = mmu_gather *tlb, ptent =3D pte_clear_uffd(ptent); =20 /* - * The uffd bit on a VM_UFFD_RWP VMA carries PROT_NONE + * The uffd bit on a uffd-RWP VMA carries PROT_NONE * semantics. If mprotect() or NUMA hinting changed the * base protection, restore PAGE_NONE so the PTE still * traps on any access. pte_modify() preserves diff --git a/mm/shmem.c b/mm/shmem.c index 2138a4e6b549..c8db9f93dde1 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3220,7 +3220,7 @@ static struct folio *shmem_get_folio_noalloc(struct i= node *inode, pgoff_t pgoff) return folio; } =20 -static bool shmem_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_= flags) +static bool shmem_can_userfault(struct vm_area_struct *vma, unsigned int m= ode) { return true; } diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 83587d34b189..193f6e65d875 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -50,10 +50,10 @@ struct mfill_state { pmd_t *pmd; }; =20 -static bool anon_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_f= lags) +static bool anon_can_userfault(struct vm_area_struct *vma, unsigned int mo= de) { /* anonymous memory does not support MINOR mode */ - if (vm_flags & VM_UFFD_MINOR) + if (mode & UFFD_MODE_MINOR) return false; return true; } @@ -462,7 +462,7 @@ static int mfill_copy_folio_locked(struct folio *folio,= unsigned long src_addr) } =20 #define MFILL_RETRY_STATE_VMA_FLAGS \ - append_vma_flags(__VMA_UFFD_FLAGS, VMA_SHARED_BIT) + append_vma_flags(VMA_UFFD, VMA_SHARED_BIT) =20 /* * VMA state saved before dropping the locks in mfill_copy_folio_retry(). @@ -2194,7 +2194,7 @@ static ssize_t move_pages(struct userfaultfd_ctx *ctx= , unsigned long dst_start, return moved ? moved : err; } =20 -static bool vma_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_fl= ags, +static bool vma_can_userfault(struct vm_area_struct *vma, unsigned int mod= e, bool wp_async) { const struct vm_uffd_ops *ops =3D vma_uffd_ops(vma); @@ -2205,13 +2205,11 @@ static bool vma_can_userfault(struct vm_area_struct= *vma, vm_flags_t vm_flags, if (!is_vm_hugetlb_page(vma) && (vma->vm_flags & VM_SPECIAL)) return false; =20 - vm_flags &=3D __VM_UFFD_FLAGS; - /* * If WP is the only mode enabled and context is wp async, allow any * memory type. */ - if (wp_async && (vm_flags =3D=3D VM_UFFD_WP)) + if (wp_async && (mode =3D=3D UFFD_MODE_WP)) return true; =20 /* For any other mode reject VMAs that don't implement vm_uffd_ops */ @@ -2222,19 +2220,31 @@ static bool vma_can_userfault(struct vm_area_struct= *vma, vm_flags_t vm_flags, * If user requested uffd-wp but not enabled pte markers for * uffd-wp, then only anonymous memory is supported */ - if (!uffd_supports_wp_marker() && (vm_flags & VM_UFFD_WP) && + if (!uffd_supports_wp_marker() && (mode & UFFD_MODE_WP) && !vma_is_anonymous(vma)) return false; =20 - return ops->can_userfault(vma, vm_flags); + return ops->can_userfault(vma, mode); } =20 -static void userfaultfd_set_vm_flags(struct vm_area_struct *vma, - vm_flags_t vm_flags) +static void userfaultfd_set_ctx(struct vm_area_struct *vma, + struct userfaultfd_ctx *ctx, + unsigned int mode) { - const bool uffd_wp_changed =3D (vma->vm_flags ^ vm_flags) & VM_UFFD_WP; + const bool uffd_wp_changed =3D (uffd_mode(vma) ^ mode) & UFFD_MODE_WP; + + vma_start_write(vma); + + vma->vm_uffd_state =3D (struct vm_uffd_state){ + .ctx =3D ctx, + .mode =3D mode, + }; + + if (mode) + vma_set_flags(vma, VMA_UFFD_BIT); + else + vma_clear_flags(vma, VMA_UFFD_BIT); =20 - vm_flags_reset(vma, vm_flags); /* * For shared mappings, we want to enable writenotify while * userfaultfd-wp is enabled (see vma_wants_writenotify()). We'll simply @@ -2244,16 +2254,6 @@ static void userfaultfd_set_vm_flags(struct vm_area_= struct *vma, vma_set_page_prot(vma); } =20 -static void userfaultfd_set_ctx(struct vm_area_struct *vma, - struct userfaultfd_ctx *ctx, - vm_flags_t vm_flags) -{ - vma_start_write(vma); - vma->vm_uffd_state =3D (struct vm_uffd_state){ctx}; - userfaultfd_set_vm_flags(vma, - (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags); -} - static void userfaultfd_reset_ctx(struct vm_area_struct *vma) { userfaultfd_set_ctx(vma, NULL, 0); @@ -2269,7 +2269,7 @@ static struct vm_area_struct *userfaultfd_clear_vma(s= truct vma_iterator *vmi, bool give_up_on_oom =3D false; vma_flags_t new_vma_flags =3D vma->flags; =20 - vma_flags_clear_mask(&new_vma_flags, __VMA_UFFD_FLAGS); + vma_flags_clear_mask(&new_vma_flags, VMA_UFFD); =20 /* * If we are modifying only and not splitting, just give up on the merge @@ -2313,11 +2313,10 @@ static struct vm_area_struct *userfaultfd_clear_vma= (struct vma_iterator *vmi, /* Assumes mmap write lock taken, and mm_struct pinned. */ static int userfaultfd_register_range(struct userfaultfd_ctx *ctx, struct vm_area_struct *vma, - vm_flags_t vm_flags, + unsigned int mode, unsigned long start, unsigned long end, bool wp_async) { - vma_flags_t vma_flags =3D legacy_to_vma_flags(vm_flags); VMA_ITERATOR(vmi, ctx->mm, start); struct vm_area_struct *prev =3D vma_prev(&vmi); unsigned long vma_end; @@ -2329,7 +2328,7 @@ static int userfaultfd_register_range(struct userfaul= tfd_ctx *ctx, for_each_vma_range(vmi, vma, end) { cond_resched(); =20 - VM_WARN_ON_ONCE(!vma_can_userfault(vma, vm_flags, wp_async)); + VM_WARN_ON_ONCE(!vma_can_userfault(vma, mode, wp_async)); VM_WARN_ON_ONCE(vma->vm_uffd_state.ctx && vma->vm_uffd_state.ctx !=3D ctx); VM_WARN_ON_ONCE(!vma_test(vma, VMA_MAYWRITE_BIT)); @@ -2339,28 +2338,31 @@ static int userfaultfd_register_range(struct userfa= ultfd_ctx *ctx, * userfaultfd and with the right tracking mode too. */ if (vma->vm_uffd_state.ctx =3D=3D ctx && - vma_test_all_mask(vma, vma_flags)) + (uffd_mode(vma) & mode) =3D=3D mode) goto skip; =20 /* * Pre-scan in userfaultfd_register() already rejected mode - * switches that would drop VM_UFFD_WP or VM_UFFD_RWP, so a - * stray bit here is a bug. + * switches that would drop WP or RWP, so a stray bit here + * is a bug. */ VM_WARN_ON_ONCE(vma->vm_uffd_state.ctx =3D=3D ctx && - vma->vm_flags & (VM_UFFD_WP | VM_UFFD_RWP) & ~vm_flags); + uffd_mode(vma) & + (UFFD_MODE_WP | UFFD_MODE_RWP) & ~mode); =20 if (vma->vm_start > start) start =3D vma->vm_start; vma_end =3D min(end, vma->vm_end); =20 new_vma_flags =3D vma->flags; - vma_flags_clear_mask(&new_vma_flags, __VMA_UFFD_FLAGS); - vma_flags_set_mask(&new_vma_flags, vma_flags); + vma_flags_set_mask(&new_vma_flags, VMA_UFFD); =20 vma =3D vma_modify_flags_uffd(&vmi, prev, vma, start, vma_end, &new_vma_flags, - (struct vm_uffd_state){ctx}, + (struct vm_uffd_state){ + .ctx =3D ctx, + .mode =3D mode, + }, /* give_up_on_oom =3D */false); if (IS_ERR(vma)) return PTR_ERR(vma); @@ -2370,7 +2372,7 @@ static int userfaultfd_register_range(struct userfaul= tfd_ctx *ctx, * the next vma was merged into the current one and * the current one has not been updated yet. */ - userfaultfd_set_ctx(vma, ctx, vm_flags); + userfaultfd_set_ctx(vma, ctx, mode); =20 if (is_vm_hugetlb_page(vma) && uffd_disable_huge_pmd_share(vma)) hugetlb_unshare_all_pmds(vma); @@ -2420,7 +2422,7 @@ static void userfaultfd_release_all(struct mm_struct = *mm, for_each_vma(vmi, vma) { cond_resched(); VM_WARN_ON_ONCE(!!vma->vm_uffd_state.ctx ^ - !!(vma->vm_flags & __VM_UFFD_FLAGS)); + vma_test(vma, VMA_UFFD_BIT)); if (vma->vm_uffd_state.ctx !=3D ctx) { prev =3D vma; continue; @@ -2876,9 +2878,9 @@ vm_fault_t handle_userfault(struct vm_fault *vmf, enu= m uf_reason reason) * NOTE: it should become possible to return VM_FAULT_RETRY * even if FAULT_FLAG_TRIED is set without leading to gup() * -EBUSY failures, if the userfaultfd is to be extended for - * VM_UFFD_WP tracking and we intend to arm the userfault + * WP tracking and we intend to arm the userfault * without first stopping userland access to the memory. For - * VM_UFFD_MISSING userfaults this is enough for now. + * MISSING userfaults this is enough for now. */ if (unlikely(!(vmf->flags & FAULT_FLAG_ALLOW_RETRY))) { /* @@ -3723,7 +3725,7 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, int ret; struct uffdio_register uffdio_register; struct uffdio_register __user *user_uffdio_register; - vm_flags_t vm_flags; + unsigned int mode; bool found; bool basic_ioctls; unsigned long start, end; @@ -3742,21 +3744,22 @@ static int userfaultfd_register(struct userfaultfd_= ctx *ctx, goto out; if (uffdio_register.mode & ~UFFD_API_REGISTER_MODES) goto out; - vm_flags =3D 0; + mode =3D 0; if (uffdio_register.mode & UFFDIO_REGISTER_MODE_MISSING) - vm_flags |=3D VM_UFFD_MISSING; + mode |=3D UFFD_MODE_MISSING; if (uffdio_register.mode & UFFDIO_REGISTER_MODE_WP) { if (!pgtable_supports_uffd()) goto out; =20 - vm_flags |=3D VM_UFFD_WP; + mode |=3D UFFD_MODE_WP; } if (uffdio_register.mode & UFFDIO_REGISTER_MODE_RWP) { - if (!pgtable_supports_uffd() || VM_UFFD_RWP =3D=3D VM_NONE) + if (!pgtable_supports_uffd() || + !IS_ENABLED(CONFIG_USERFAULTFD_RWP)) goto out; if (!(userfaultfd_features(ctx) & UFFD_FEATURE_RWP)) goto out; - vm_flags |=3D VM_UFFD_RWP; + mode |=3D UFFD_MODE_RWP; } =20 /* @@ -3764,14 +3767,14 @@ static int userfaultfd_register(struct userfaultfd_= ctx *ctx, * cannot coexist in the same VMA =E2=80=94 the bit would carry ambiguous * semantics. Reject the combination up front. */ - if ((vm_flags & VM_UFFD_WP) && (vm_flags & VM_UFFD_RWP)) + if ((mode & UFFD_MODE_WP) && (mode & UFFD_MODE_RWP)) goto out; =20 if (uffdio_register.mode & UFFDIO_REGISTER_MODE_MINOR) { #ifndef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR goto out; #endif - vm_flags |=3D VM_UFFD_MINOR; + mode |=3D UFFD_MODE_MINOR; } =20 ret =3D validate_range(mm, uffdio_register.range.start, @@ -3814,11 +3817,11 @@ static int userfaultfd_register(struct userfaultfd_= ctx *ctx, cond_resched(); =20 VM_WARN_ON_ONCE(!!cur->vm_uffd_state.ctx ^ - !!(cur->vm_flags & __VM_UFFD_FLAGS)); + vma_test(cur, VMA_UFFD_BIT)); =20 /* check not compatible vmas */ ret =3D -EINVAL; - if (!vma_can_userfault(cur, vm_flags, wp_async)) + if (!vma_can_userfault(cur, mode, wp_async)) goto out_unlock; =20 /* @@ -3829,7 +3832,7 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, * mprotect() must still be unregisterable, so this is not * part of vma_can_userfault(). */ - if ((vm_flags & VM_UFFD_RWP) && !vma_is_accessible(cur)) + if ((mode & UFFD_MODE_RWP) && !vma_is_accessible(cur)) goto out_unlock; =20 /* @@ -3857,7 +3860,8 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, if (end & (vma_hpagesize - 1)) goto out_unlock; } - if ((vm_flags & VM_UFFD_WP) && !(cur->vm_flags & VM_MAYWRITE)) + if ((mode & UFFD_MODE_WP) && + !vma_test(cur, VMA_MAYWRITE_BIT)) goto out_unlock; =20 /* @@ -3872,13 +3876,13 @@ static int userfaultfd_register(struct userfaultfd_= ctx *ctx, goto out_unlock; =20 /* - * Mode switches that drop VM_UFFD_WP or VM_UFFD_RWP would - * leave PTE markers without the flag that describes them; + * Mode switches that drop WP or RWP would leave PTE markers + * without the mode that describes them; * subsequent mprotect() would then promote stale markers * into the other mode. Require an unregister first. */ if (cur->vm_uffd_state.ctx =3D=3D ctx && - cur->vm_flags & (VM_UFFD_WP | VM_UFFD_RWP) & ~vm_flags) + uffd_mode(cur) & (UFFD_MODE_WP | UFFD_MODE_RWP) & ~mode) goto out_unlock; =20 /* @@ -3891,7 +3895,7 @@ static int userfaultfd_register(struct userfaultfd_ct= x *ctx, } for_each_vma_range(vmi, cur, end); VM_WARN_ON_ONCE(!found); =20 - ret =3D userfaultfd_register_range(ctx, vma, vm_flags, start, end, + ret =3D userfaultfd_register_range(ctx, vma, mode, start, end, wp_async); =20 out_unlock: @@ -3986,7 +3990,7 @@ static int userfaultfd_unregister(struct userfaultfd_= ctx *ctx, cond_resched(); =20 VM_WARN_ON_ONCE(!!cur->vm_uffd_state.ctx ^ - !!(cur->vm_flags & __VM_UFFD_FLAGS)); + vma_test(cur, VMA_UFFD_BIT)); =20 /* * Prevent unregistering through a different userfaultfd than @@ -4003,7 +4007,7 @@ static int userfaultfd_unregister(struct userfaultfd_= ctx *ctx, * provides for more strict behavior to notice * unregistration errors. */ - if (!vma_can_userfault(cur, cur->vm_flags, wp_async)) + if (!vma_can_userfault(cur, uffd_mode(cur), wp_async)) goto out_unlock; =20 found =3D true; @@ -4024,7 +4028,8 @@ static int userfaultfd_unregister(struct userfaultfd_= ctx *ctx, goto skip; =20 VM_WARN_ON_ONCE(vma->vm_uffd_state.ctx !=3D ctx); - VM_WARN_ON_ONCE(!vma_can_userfault(vma, vma->vm_flags, wp_async)); + VM_WARN_ON_ONCE(!vma_can_userfault(vma, uffd_mode(vma), + wp_async)); VM_WARN_ON_ONCE(!(vma->vm_flags & VM_MAYWRITE)); =20 if (vma->vm_start > start) @@ -4329,12 +4334,12 @@ static __u64 uffd_api_available_features(void) UFFD_FEATURE_WP_ASYNC); /* * RWP needs both PROT_NONE support and the uffd PTE bit. The - * VM_UFFD_RWP check covers compile-time unavailability; the + * IS_ENABLED check covers compile-time unavailability; the * pgtable_supports_uffd() check covers runtime (e.g. riscv * without the SVRSW60T59B extension) where the PTE bit is declared * but not actually usable. */ - if (VM_UFFD_RWP =3D=3D VM_NONE || !pgtable_supports_uffd()) + if (!IS_ENABLED(CONFIG_USERFAULTFD_RWP) || !pgtable_supports_uffd()) f &=3D ~(UFFD_FEATURE_RWP | UFFD_FEATURE_RWP_ASYNC); return f; } diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/du= p.h index 1a01c3529d22..05a39c14eab2 100644 --- a/tools/testing/vma/include/dup.h +++ b/tools/testing/vma/include/dup.h @@ -109,7 +109,7 @@ enum { DECLARE_VMA_BIT(MAYSHARE, 7), DECLARE_VMA_BIT(GROWSDOWN, 8), /* general info on the segment */ #ifdef CONFIG_MMU - DECLARE_VMA_BIT(UFFD_MISSING, 9),/* missing pages tracking */ + DECLARE_VMA_BIT(UFFD, 9), /* userfaultfd registered */ #else /* nommu: R/O MAP_PRIVATE mapping that might overlay a file mapping */ DECLARE_VMA_BIT(MAYOVERLAY, 9), @@ -117,7 +117,7 @@ enum { /* Page-ranges managed without "struct page", just pure PFN */ DECLARE_VMA_BIT(PFNMAP, 10), DECLARE_VMA_BIT(MAYBE_GUARD, 11), - DECLARE_VMA_BIT(UFFD_WP, 12), /* wrprotect pages tracking */ + /* Bit 12 is free */ DECLARE_VMA_BIT(LOCKED, 13), DECLARE_VMA_BIT(IO, 14), /* Memory mapped I/O or similar */ DECLARE_VMA_BIT(SEQ_READ, 15), /* App will access data sequentially */ @@ -158,7 +158,7 @@ enum { #else DECLARE_VMA_BIT(DROPPABLE, 40), #endif - DECLARE_VMA_BIT(UFFD_MINOR, 41), + /* Bit 41 is free */ DECLARE_VMA_BIT(SEALED, 42), /* Flags that reuse flags above. */ DECLARE_VMA_BIT_ALIAS(PKEY_BIT0, HIGH_ARCH_0), @@ -211,14 +211,13 @@ enum { #define VM_MAYSHARE INIT_VM_FLAG(MAYSHARE) #define VM_GROWSDOWN INIT_VM_FLAG(GROWSDOWN) #ifdef CONFIG_MMU -#define VM_UFFD_MISSING INIT_VM_FLAG(UFFD_MISSING) +#define VM_UFFD INIT_VM_FLAG(UFFD) #else -#define VM_UFFD_MISSING VM_NONE +#define VM_UFFD VM_NONE #define VM_MAYOVERLAY INIT_VM_FLAG(MAYOVERLAY) #endif #define VM_PFNMAP INIT_VM_FLAG(PFNMAP) #define VM_MAYBE_GUARD INIT_VM_FLAG(MAYBE_GUARD) -#define VM_UFFD_WP INIT_VM_FLAG(UFFD_WP) #define VM_LOCKED INIT_VM_FLAG(LOCKED) #define VM_IO INIT_VM_FLAG(IO) #define VM_SEQ_READ INIT_VM_FLAG(SEQ_READ) @@ -297,11 +296,6 @@ enum { #define VM_MTE VM_NONE #define VM_MTE_ALLOWED VM_NONE #endif -#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR -#define VM_UFFD_MINOR INIT_VM_FLAG(UFFD_MINOR) -#else -#define VM_UFFD_MINOR VM_NONE -#endif #ifdef CONFIG_64BIT #define VM_ALLOW_ANY_UNCACHED INIT_VM_FLAG(ALLOW_ANY_UNCACHED) #define VM_SEALED INIT_VM_FLAG(SEALED) @@ -387,7 +381,7 @@ enum { =20 #define VMA_IGNORE_MERGE_FLAGS VMA_STICKY_FLAGS =20 -#define VM_COPY_ON_FORK (VM_PFNMAP | VM_MIXEDMAP | VM_UFFD_WP | VM_MAYBE_G= UARD) +#define VM_COPY_ON_FORK (VM_PFNMAP | VM_MIXEDMAP | VM_MAYBE_GUARD) =20 #define pgprot_val(x) ((x).pgprot) #define __pgprot(x) ((pgprot_t) { (x) } ) --=20 2.53.0