initial work on making VMA flags a bitmap
Subsystems (11)
v3 cover initial work on making VMA flags a bitmap
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
This is necessarily a highly iterative process given the extensive use of VMA flags throughout the kernel, so we start by performing basic steps.
Firstly, we declare VMA flags by bit number rather than by value, retaining the VM_xxx fields but in terms of these newly introduced VMA_xxx_BIT fields.
While we are here, we use sparse annotations to ensure that, when dealing with VMA bit number parameters, we cannot be passed values which are not declared as such - providing some useful type safety.
We then introduce an opaque VMA flag type, much like the opaque mm_struct flag type introduced in commit bb6525f2f8c4 ("mm: add bitmap mm->flags field"), which we establish in union with vma->vm_flags (but still set at system word size meaning there is no functional or data type size change).
We update the vm_flags_xxx() helpers to use this new bitmap, introducing sensible helpers to do so.
This series lays the foundation for further work to expand the use of bitmap VMA flags and eventually eliminate these arbitrary restrictions.
v3:
* Rebased against mm-new.
* Squashed fixups in to series.
* Propagated tags (thanks Vlasta!).
* After off-list discussion with Pedro Falcato, added defensive code in vm_flags_reset_once() to only clear bits higher than the first sytem word, retaining write-once semantics for the first system word, which is what callers are relying upon.
v2:
* Corrected kdoc for vma_flag_t.
* Introduced DECLARE_VMA_BIT() as per Jason. We can't also declare the VMA flags in the enum as this breaks assumptions in the kernel, resulting in errors like 'enum constant in boolean context [-Werror=int-in-bool-context]'.
* Dropped the conversion patch - To make life simpler this cycle, let's just fixup the flag declarations and introduce the new field type and introduce vm_flags_*() changes. We can do more later.
* Split out VMA testing vma->__vm_flags change.
* Fixed vma_flag_*_atomic() helper functions for sparse purposes to work with vma_flag_t.
* Fixed rust breakages as reported by Nico and help provided by Alice. For now we are doing a minimal fix, we can do a more substantial one once the VMA flag helper functions are introduced in an upcoming series.
https://lore.kernel.org/all/[email protected]>/
v1:
https://lore.kernel.org/all/[email protected]/
Lorenzo Stoakes (4):
mm: declare VMA flags by bit
mm: simplify and rename mm flags function for clarity tools/testing/vma: eliminate dependency on vma->__vm_flags
mm: introduce VMA flags bitmap type
fs/proc/task_mmu.c | 4 +- include/linux/mm.h | 401 +++++++++++++++------------ include/linux/mm_types.h | 78 +++++- kernel/fork.c | 4 +- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- rust/bindgen_parameters | 25 ++ rust/bindings/bindings_helper.h | 25 ++ rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma.c | 20 +- tools/testing/vma/vma_internal.h | 454 ++++++++++++++++++++++++++----- 11 files changed, 742 insertions(+), 275 deletions(-)
--
2.51.2
PATCH v3 1/4 mm: declare VMA flags by bit
In order to lay the groundwork for VMA flags being a bitmap rather than a system word in size, we need to be able to consistently refer to VMA flags by bit number rather than value.
Take this opportunity to do so in an enum which we which is additionally useful for tooling to extract metadata from.
This additionally makes it very clear which bits are being used for what at a glance.
We use the VMA_ prefix for the bit values as it is logical to do so since these reference VMAs. We consistently suffix with _BIT to make it clear what the values refer to.
We declare bit values even when the flags that use them would not be enabled by config options as this is simply clearer and clearly defines what bit numbers are used for what, at no additional cost.
We declare a sparse-bitwise type vma_flag_t which ensures that users can't pass around invalid VMA flags by accident and prepares for future work towards VMA flags being a bitmap where we want to ensure bit values are type safe.
To make life easier, we declare some macro helpers - DECLARE_VMA_BIT() allows us to avoid duplication in the enum bit number declarations (and maintaining the sparse __bitwise attribute), and INIT_VM_FLAG() is used to assist with declaration of flags.
Unfortunately we can't declare both in the enum, as we run into issue with logic in the kernel requiring that flags are preprocessor definitions, and additionally we cannot have a macro which declares another macro so we must define each flag macro directly.
Additionally, update the VMA userland testing vma_internal.h header to include these changes.
We also have to fix the parameters to the vma_flag_*_atomic() functions since VMA_MAYBE_GUARD_BIT is now of type vma_flag_t and sparse will complain otherwise.
We have to update some rather silly if-deffery found in mm/task_mmu.c which would otherwise break.
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
--- fs/proc/task_mmu.c | 4 +- include/linux/mm.h | 379 +++++++++++++++++-------------- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- rust/bindgen_parameters | 25 ++ rust/bindings/bindings_helper.h | 25 ++ tools/testing/vma/vma_internal.h | 304 +++++++++++++++++++++---- 7 files changed, 524 insertions(+), 217 deletions(-)
fs/proc/task_mmu.c +2 -2
@@ -1183,10 +1183,10 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_PKEY_BIT0)] = "", [ilog2(VM_PKEY_BIT1)] = "", [ilog2 (VM_PKEY_BIT2 )] ="" , -#if VM_PKEY_BIT3 +#if CONFIG_ARCH_PKEY_BITS > 3 [ilog2 (VM_PKEY_BIT3 )] ="" , #endif -#if VM_PKEY_BIT4 +#if CONFIG_ARCH_PKEY_BITS > 4 [ilog2(VM_PKEY_BIT4)] = "", #endif #endif /* CONFIG_ARCH_HAS_PKEYS */
include/linux/mm.h +211 -168
471 lines not on this page · raw message
mm/khugepaged.c +1 -1
@@ -1740,7 +1740,7 @@ static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)* obtained on guard region installation after the flag is set, so this * check being performed under this lock excludes races. */ -if (vma_flag_test_atomic (vma,VM_MAYBE_GUARD_BIT )) +if (vma_flag_test_atomic (vma,VMA_MAYBE_GUARD_BIT ))return false;return true;
mm/madvise.c +1 -1
@@ -1142,7 +1142,7 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)* acquire an mmap/VMA write lock to read it. All remaining readers may * or may not see the flag set, but we don't care. */ -vma_flag_set_atomic (vma,VM_MAYBE_GUARD_BIT ); +vma_flag_set_atomic (vma,VMA_MAYBE_GUARD_BIT );/* * If anonymous and we are establishing page tables the VMA ought to
rust/bindgen_parameters +25 -0
@@ -35,6 +35,31 @@ # recognized, block generation of the non-helper constants. --blocklist-item ARCH_SLAB_MINALIGN --blocklist-item ARCH_KMALLOC_MINALIGN +--blocklist-item VM_MERGEABLE +--blocklist-item VM_READ +--blocklist-item VM_WRITE +--blocklist-item VM_EXEC +--blocklist-item VM_SHARED +--blocklist-item VM_MAYREAD +--blocklist-item VM_MAYWRITE +--blocklist-item VM_MAYEXEC +--blocklist-item VM_MAYEXEC +--blocklist-item VM_PFNMAP +--blocklist-item VM_IO +--blocklist-item VM_DONTCOPY +--blocklist-item VM_DONTEXPAND +--blocklist-item VM_LOCKONFAULT +--blocklist-item VM_ACCOUNT +--blocklist-item VM_NORESERVE +--blocklist-item VM_HUGETLB +--blocklist-item VM_SYNC +--blocklist-item VM_ARCH_1 +--blocklist-item VM_WIPEONFORK +--blocklist-item VM_DONTDUMP +--blocklist-item VM_SOFTDIRTY +--blocklist-item VM_MIXEDMAP +--blocklist-item VM_HUGEPAGE +--blocklist-item VM_NOHUGEPAGE # Structs should implement `Zeroable` when all of their fields do. --with-derive-custom-struct .*=MaybeZeroable
rust/bindings/bindings_helper.h +25 -0
@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC =XA_FLAGS_ALLOC ;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 =XA_FLAGS_ALLOC1 ; +const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE =VM_MERGEABLE ; +const vm_flags_t RUST_CONST_HELPER_VM_READ =VM_READ ; +const vm_flags_t RUST_CONST_HELPER_VM_WRITE =VM_WRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_EXEC =VM_EXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_SHARED =VM_SHARED ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_PFNMAP =VM_PFNMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_IO =VM_IO ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTCOPY =VM_DONTCOPY ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTEXPAND =VM_DONTEXPAND ; +const vm_flags_t RUST_CONST_HELPER_VM_LOCKONFAULT =VM_LOCKONFAULT ; +const vm_flags_t RUST_CONST_HELPER_VM_ACCOUNT =VM_ACCOUNT ; +const vm_flags_t RUST_CONST_HELPER_VM_NORESERVE =VM_NORESERVE ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGETLB =VM_HUGETLB ; +const vm_flags_t RUST_CONST_HELPER_VM_SYNC =VM_SYNC ; +const vm_flags_t RUST_CONST_HELPER_VM_ARCH_1 =VM_ARCH_1 ; +const vm_flags_t RUST_CONST_HELPER_VM_WIPEONFORK =VM_WIPEONFORK ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTDUMP =VM_DONTDUMP ; +const vm_flags_t RUST_CONST_HELPER_VM_SOFTDIRTY =VM_SOFTDIRTY ; +const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =VM_MIXEDMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =VM_HUGEPAGE ; +const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =VM_NOHUGEPAGE ;#if IS_ENABLED (CONFIG_ANDROID_BINDER_IPC_RUST )#include "../../drivers/android/binder/rust_binder.h"
tools/testing/vma/vma_internal.h +259 -45
327 lines not on this page · raw message
Signature · 1 line
2.51.2
Re: [PATCH v3 1/4] mm: declare VMA flags by bit
Quoted 40 lines · Lorenzo Stoakes
In order to lay the groundwork for VMA flags being a bitmap rather than a system word in size, we need to be able to consistently refer to VMA flags by bit number rather than value.
Take this opportunity to do so in an enum which we which is additionally useful for tooling to extract metadata from.
This additionally makes it very clear which bits are being used for what at a glance.
We use the
VMA_prefix for the bit values as it is logical to do so since these reference VMAs. We consistently suffix with_BITto make it clear what the values refer to.We declare bit values even when the flags that use them would not be enabled by config options as this is simply clearer and clearly defines what bit numbers are used for what, at no additional cost.
We declare a sparse-bitwise type
vma_flag_twhich ensures that users can't pass around invalid VMA flags by accident and prepares for future work towards VMA flags being a bitmap where we want to ensure bit values are type safe.To make life easier, we declare some macro helpers -
DECLARE_VMA_BIT()allows us to avoid duplication in the enum bit number declarations (and maintaining the sparse__bitwiseattribute), andINIT_VM_FLAG()is used to assist with declaration of flags.Unfortunately we can't declare both in the enum, as we run into issue with logic in the kernel requiring that flags are preprocessor definitions, and additionally we cannot have a macro which declares another macro so we must define each flag macro directly.
Additionally, update the VMA userland testing
vma_internal.hheader to include these changes.We also have to fix the parameters to the vma_flag_*_atomic() functions since
VMA_MAYBE_GUARD_BITis now of typevma_flag_tand sparse will complain otherwise.
Quoted 8 lines
We have to update some rather silly if-deffery found in
mm/task_mmu.cwhich would otherwise break.Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
Signed-off-by Lorenzo Stoakes <[email protected]>Acked-by Vlastimil Babka <[email protected]>
Scary but cromulent-looking. Thanks :)
--
Pedro
Re: [PATCH v3 1/4] mm: declare VMA flags by bit
In reply to Lorenzo StoakesOn Tue, 25 Nov 2025 10:00:59 +0000 Lorenzo Stoakes <[email protected]> wrote:
[ ... ]
Quoted 4 lines
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
I did a run of all the MM commits from 6.18 to today's linus, and this one
had a copy/paste error. I'd normally just send a patch for this, but in
terms of showing the review output:
Quoted 5 lines
rust/bindings/bindings_helper.h +0
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;
[ ... ]
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 120
Quoted 4 lines
rust/bindings/bindings_helper.h +4
-0+const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ;
^^^^^^^^^^
Should this be VM_MAYSHARE instead of VM_MAYEXEC? This appears to be a copy-paste error that would cause Rust code using VmFlags::MAYSHARE to get bit 6 (VM_MAYEXEC) instead of bit 7 (VM_MAYSHARE).
The pattern of the preceding lines shows each constant should reference its matching flag:
RUST_CONST_HELPER_VM_MAYREAD = VM_MAYREAD RUST_CONST_HELPER_VM_MAYWRITE = VM_MAYWRITE RUST_CONST_HELPER_VM_MAYEXEC = VM_MAYEXEC RUST_CONST_HELPER_VM_MAYSHARE = VM_MAYSHARE <- expected
Quoted 1 line
+const
vm_flags_tRUST_CONST_HELPER_VM_PFNMAP=VM_PFNMAP;
[ ... ]
Alice Ryhl
maintainerRe: [PATCH v3 1/4] mm: declare VMA flags by bit
Quoted 31 lines · Chris Mason
On Tue, 25 Nov 2025 10:00:59 +0000 Lorenzo Stoakes <[email protected]> wrote:
[ ... ]
Quoted 4 lines
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
I did a run of all the MM commits from 6.18 to today's linus, and this one
had a copy/paste error. I'd normally just send a patch for this, but in
terms of showing the review output:Quoted 5 lines
rust/bindings/bindings_helper.h +0
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;[ ... ]
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 120
Quoted 4 lines
rust/bindings/bindings_helper.h +4
-0+const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ;^^^^^^^^^^Should this be
VM_MAYSHAREinstead ofVM_MAYEXEC? This appears to be a copy-paste error that would cause Rust code usingVmFlags::MAYSHAREto get bit 6 (VM_MAYEXEC) instead of bit 7 (VM_MAYSHARE).
Quoted 9 lines
The pattern of the preceding lines shows each constant should reference its matching flag:
RUST_CONST_HELPER_VM_MAYREAD=VM_MAYREADRUST_CONST_HELPER_VM_MAYWRITE=VM_MAYWRITERUST_CONST_HELPER_VM_MAYEXEC=VM_MAYEXECRUST_CONST_HELPER_VM_MAYSHARE=VM_MAYSHARE<- expectedQuoted 1 line
+const
vm_flags_tRUST_CONST_HELPER_VM_PFNMAP=VM_PFNMAP;
Uh, good catch. Do you want to send a fix patch?
Alice
Re: [PATCH v3 1/4] mm: declare VMA flags by bit
Quoted 35 lines · Alice Ryhl
Quoted 34 lines · Chris Mason
On Tue, 25 Nov 2025 10:00:59 +0000 Lorenzo Stoakes <[email protected]> wrote:
[ ... ]
Quoted 4 lines
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
I did a run of all the MM commits from 6.18 to today's linus, and this one
had a copy/paste error. I'd normally just send a patch for this, but in
terms of showing the review output:Quoted 5 lines
rust/bindings/bindings_helper.h +0
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;[ ... ]
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 120
Quoted 4 lines
rust/bindings/bindings_helper.h +4
-0+const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ;^^^^^^^^^^Should this be
VM_MAYSHAREinstead ofVM_MAYEXEC? This appears to be a copy-paste error that would cause Rust code usingVmFlags::MAYSHAREto get bit 6 (VM_MAYEXEC) instead of bit 7 (VM_MAYSHARE).The pattern of the preceding lines shows each constant should reference its matching flag:
Quoted 8 lines
Quoted 6 lines
RUST_CONST_HELPER_VM_MAYREAD=VM_MAYREADRUST_CONST_HELPER_VM_MAYWRITE=VM_MAYWRITERUST_CONST_HELPER_VM_MAYEXEC=VM_MAYEXECRUST_CONST_HELPER_VM_MAYSHARE=VM_MAYSHARE<- expectedQuoted 1 line
+const
vm_flags_tRUST_CONST_HELPER_VM_PFNMAP=VM_PFNMAP;Uh, good catch. Do you want to send a fix patch?
It's in 6.18 so would need to be a Cc: stable patch with a Fixes etc. rather than a fix-patch, unless that's what you meant?
Quoted 2 lines
Alice
Alice Ryhl
maintainerRe: [PATCH v3 1/4] mm: declare VMA flags by bit
Quoted 42 lines · Lorenzo Stoakes
Quoted 40 lines · Alice Ryhl
Quoted 39 lines · Chris Mason
On Tue, 25 Nov 2025 10:00:59 +0000 Lorenzo Stoakes <[email protected]> wrote:
[ ... ]
Quoted 4 lines
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
I did a run of all the MM commits from 6.18 to today's linus, and this one
had a copy/paste error. I'd normally just send a patch for this, but in
terms of showing the review output:Quoted 5 lines
rust/bindings/bindings_helper.h +0
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;[ ... ]
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 120
Quoted 4 lines
rust/bindings/bindings_helper.h +4
-0+const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ;^^^^^^^^^^Should this be
VM_MAYSHAREinstead ofVM_MAYEXEC? This appears to be a copy-paste error that would cause Rust code usingVmFlags::MAYSHAREto get bit 6 (VM_MAYEXEC) instead of bit 7 (VM_MAYSHARE).The pattern of the preceding lines shows each constant should reference its matching flag:
RUST_CONST_HELPER_VM_MAYREAD=VM_MAYREADRUST_CONST_HELPER_VM_MAYWRITE=VM_MAYWRITERUST_CONST_HELPER_VM_MAYEXEC=VM_MAYEXECRUST_CONST_HELPER_VM_MAYSHARE=VM_MAYSHARE<- expected
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
+const
vm_flags_tRUST_CONST_HELPER_VM_PFNMAP=VM_PFNMAP;Uh, good catch. Do you want to send a fix patch?
It's in 6.18 so would need to be a Cc: stable patch with a Fixes etc. rather than a fix-patch, unless that's what you meant?
That's what I meant, yeah.
Alice
Re: [PATCH v3 1/4] mm: declare VMA flags by bit
In reply to Chris MasonQuoted 33 lines · Chris Mason
On Tue, 25 Nov 2025 10:00:59 +0000 Lorenzo Stoakes <[email protected]> wrote:
[ ... ]
Quoted 4 lines
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
I did a run of all the MM commits from 6.18 to today's linus, and this one
had a copy/paste error. I'd normally just send a patch for this, but in
terms of showing the review output:Quoted 5 lines
rust/bindings/bindings_helper.h +0
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;[ ... ]
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 120
Quoted 4 lines
rust/bindings/bindings_helper.h +4
-0+const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ;^^^^^^^^^^Should this be
VM_MAYSHAREinstead ofVM_MAYEXEC? This appears to be a copy-paste error that would cause Rust code usingVmFlags::MAYSHAREto get bit 6 (VM_MAYEXEC) instead of bit 7 (VM_MAYSHARE).The pattern of the preceding lines shows each constant should reference its matching flag:
Quoted 10 lines
RUST_CONST_HELPER_VM_MAYREAD=VM_MAYREADRUST_CONST_HELPER_VM_MAYWRITE=VM_MAYWRITERUST_CONST_HELPER_VM_MAYEXEC=VM_MAYEXECRUST_CONST_HELPER_VM_MAYSHARE=VM_MAYSHARE<- expectedQuoted 1 line
+const
vm_flags_tRUST_CONST_HELPER_VM_PFNMAP=VM_PFNMAP;[ ... ]
Oopsies!
I can send a patch unless you were planning to!
Cheers, Lorenzo
Re: [PATCH v3 1/4] mm: declare VMA flags by bit
Quoted 41 lines · Lorenzo Stoakes
Quoted 40 lines · Chris Mason
On Tue, 25 Nov 2025 10:00:59 +0000 Lorenzo Stoakes <[email protected]> wrote:
[ ... ]
Quoted 4 lines
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
I did a run of all the MM commits from 6.18 to today's linus, and this one
had a copy/paste error. I'd normally just send a patch for this, but in
terms of showing the review output:Quoted 5 lines
rust/bindings/bindings_helper.h +0
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;[ ... ]
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 120
Quoted 4 lines
rust/bindings/bindings_helper.h +4
-0+const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ;^^^^^^^^^^Should this be
VM_MAYSHAREinstead ofVM_MAYEXEC? This appears to be a copy-paste error that would cause Rust code usingVmFlags::MAYSHAREto get bit 6 (VM_MAYEXEC) instead of bit 7 (VM_MAYSHARE).The pattern of the preceding lines shows each constant should reference its matching flag:
RUST_CONST_HELPER_VM_MAYREAD=VM_MAYREADRUST_CONST_HELPER_VM_MAYWRITE=VM_MAYWRITERUST_CONST_HELPER_VM_MAYEXEC=VM_MAYEXECRUST_CONST_HELPER_VM_MAYSHARE=VM_MAYSHARE<- expectedQuoted 1 line
+const
vm_flags_tRUST_CONST_HELPER_VM_PFNMAP=VM_PFNMAP;
Quoted 7 lines
Quoted 3 lines
[ ... ]
Oopsies!
I can send a patch unless you were planning to!
Please do, I'm still going through the rest of the commits.
-chris
PATCH v3 2/4 mm: simplify and rename mm flags function for clarity
In reply to Lorenzo StoakesThe __mm_flags_set_word() function is slightly ambiguous - we use 'set' to refer to setting individual bits (such as in mm_flags_set()) but here we use it to refer to overwriting the value altogether.
Rename it to __mm_flags_overwrite_word() to eliminate this ambiguity.
We additionally simplify the functions, eliminating unnecessary bitmap_xxx() operations (the compiler would have optimised these out but it's worth being as clear as we can be here).
--- include/linux/mm_types.h | 14 +++++--------- kernel/fork.c | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-)
include/linux/mm_types.h +5 -9
@@ -1314,15 +1314,13 @@ struct mm_struct {unsigned long cpu_bitmap[]; }; -/* Set the first system word of mm flags, non-atomically. */ -static inline void __mm_flags_set_word (struct mm_struct *mm,unsigned long value) +/* Copy value to the first system word of mm flags, non-atomically. */ +static inline void __mm_flags_overwrite_word (struct mm_struct *mm,unsigned long value) { -unsigned long *bitmap =ACCESS_PRIVATE (&mm->flags, __mm_flags); - -bitmap_copy (bitmap, &value,BITS_PER_LONG ); + *ACCESS_PRIVATE (&mm->flags, __mm_flags) = value; } -/* Obtain a read-only view of the bitmap. */ +/* Obtain a read-only view of the mm flags bitmap. */ static inline const unsigned long *__mm_flags_get_bitmap (const struct mm_struct *mm) {return (const unsigned long *)ACCESS_PRIVATE (&mm->flags, __mm_flags);
@@ -1331,9 +1329,7 @@ static inline const unsigned long *__mm_flags_get_bitmap(const struct mm_struct/* Read the first system word of mm flags, non-atomically. */ static inline unsigned long __mm_flags_get_word (const struct mm_struct *mm) { -const unsigned long *bitmap =__mm_flags_get_bitmap (mm); - -return bitmap_read (bitmap,0 ,BITS_PER_LONG ); +return *__mm_flags_get_bitmap (mm); }/*
kernel/fork.c +2 -2
@@ -1061,10 +1061,10 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,if (current->mm) {unsigned long flags =__mm_flags_get_word (current->mm); -__mm_flags_set_word (mm,mmf_init_legacy_flags (flags)); +__mm_flags_overwrite_word (mm,mmf_init_legacy_flags (flags)); mm->def_flags = current->mm->def_flags &VM_INIT_DEF_MASK ; }else { -__mm_flags_set_word (mm, default_dump_filter); +__mm_flags_overwrite_word (mm, default_dump_filter); mm->def_flags =0 ; }
Signature · 1 line
2.51.2
Re: [PATCH v3 2/4] mm: simplify and rename mm flags function for clarity
Quoted 6 lines · Lorenzo Stoakes
The
__mm_flags_set_word()function is slightly ambiguous - we use 'set' to refer to setting individual bits (such as inmm_flags_set()) but here we use it to refer to overwriting the value altogether.Rename it to
__mm_flags_overwrite_word()to eliminate this ambiguity.
write_word()?
Quoted 6 lines
We additionally simplify the functions, eliminating unnecessary
bitmap_xxx()operations (the compiler would have optimised these out but it's worth being as clear as we can be here).Signed-off-by Lorenzo Stoakes <[email protected]>Acked-by Vlastimil Babka <[email protected]>
Anyway:
Signature · 1 line
Pedro
PATCH v3 3/4 tools/testing/vma: eliminate dependency on vma->__vm_flags
In reply to Lorenzo StoakesThe userland VMA test code relied on an internal implementation detail - the existence of vma->__vm_flags to directly access VMA flags. There is no need to do so when we have the vm_flags_*() helper functions available.
This is ugly, but also a subsequent commit will eliminate this field altogether so this will shortly become broken.
This patch has us utilise the helper functions instead.
--- tools/testing/vma/vma.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
tools/testing/vma/vma.c +10 -10
@@ -69,18 +69,18 @@ static struct vm_area_struct *alloc_vma(struct mm_struct *mm, pgoff_t pgoff, vm_flags_t vm_flags) { -struct vm_area_struct *ret =vm_area_alloc (mm); +struct vm_area_struct *vma =vm_area_alloc (mm); -if (ret ==NULL ) +if (vma ==NULL )return NULL ; - ret->vm_start = start; - ret->vm_end = end; - ret->vm_pgoff = pgoff; - ret->__vm_flags = vm_flags; -vma_assert_detached (ret); + vma->vm_start = start; + vma->vm_end = end; + vma->vm_pgoff = pgoff; +vm_flags_reset (vma, vm_flags); +vma_assert_detached (vma); -return ret; +return vma; }/* Helper function to allocate a VMA and link it to the tree. */
@@ -714,7 +714,7 @@ static bool test_vma_merge_special_flags(void)for (i =0 ; i <ARRAY_SIZE (special_flags); i++) {vm_flags_t special_flag = special_flags[i]; - vma_left->__vm_flags = vm_flags | special_flag; +vm_flags_reset (vma_left, vm_flags | special_flag); vmg.vm_flags = vm_flags | special_flag; vma =merge_new (&vmg);ASSERT_EQ (vma,NULL );
@@ -736,7 +736,7 @@ static bool test_vma_merge_special_flags(void)for (i =0 ; i <ARRAY_SIZE (special_flags); i++) {vm_flags_t special_flag = special_flags[i]; - vma_left->__vm_flags = vm_flags | special_flag; +vm_flags_reset (vma_left, vm_flags | special_flag); vmg.vm_flags = vm_flags | special_flag; vma =merge_existing (&vmg);ASSERT_EQ (vma,NULL );
Signature · 1 line
2.51.2
Re: [PATCH v3 3/4] tools/testing/vma: eliminate dependency on vma->__vm_flags
Quoted 11 lines · Lorenzo Stoakes
The userland VMA test code relied on an internal implementation detail - the existence of
vma->__vm_flagsto directly access VMA flags. There is no need to do so when we have the vm_flags_*() helper functions available.This is ugly, but also a subsequent commit will eliminate this field altogether so this will shortly become broken.
This patch has us utilise the helper functions instead.
Signed-off-by Lorenzo Stoakes <[email protected]>Acked-by Vlastimil Babka <[email protected]>
Signature · 1 line
Pedro
PATCH v3 4/4 mm: introduce VMA flags bitmap type
In reply to Lorenzo StoakesIt is useful to transition to using a bitmap for VMA flags so we can avoid running out of flags, especially for 32-bit kernels which are constrained to 32 flags, necessitating some features to be limited to 64-bit kernels only.
By doing so, we remove any constraint on the number of VMA flags moving forwards no matter the platform and can decide in future to extend beyond 64 if required.
We start by declaring an opaque types, vma_flags_t (which resembles mm_struct flags of type mm_flags_t), setting it to precisely the same size as vm_flags_t, and place it in union with vm_flags in the VMA declaration.
We additionally update struct vm_area_desc equivalently placing the new opaque type in union with vm_flags.
This change therefore does not impact the size of struct vm_area_struct or struct vm_area_desc.
In order for the change to be iterative and to avoid impacting performance, we designate VM_xxx declared bitmap flag values as those which must exist in the first system word of the VMA flags bitmap.
We therefore declare vma_flags_clear_all(), vma_flags_overwrite_word(), vma_flags_overwrite_word(), vma_flags_overwrite_word_once(), vma_flags_set_word() and vma_flags_clear_word() in order to allow us to update the existing vm_flags_*() functions to utilise these helpers.
This is a stepping stone towards converting users to the VMA flags bitmap and behaves precisely as before.
By doing this, we can eliminate the existing private vma->__vm_flags field in the vma->vm_flags union and replace it with the newly introduced opaque type vma_flags, which we call flags so we refer to the new bitmap field as vma->flags.
We update vma_flag_[test, set]_atomic() to account for the change also.
We adapt vm_flags_reset_once() to only clear those bits above the first system word providing write-once semantics to the first system word (which it is presumed the caller requires - and in all current use cases this is so).
As we currently only specify that the VMA flags bitmap size is equal to BITS_PER_LONG number of bits, this is a noop, but is defensive in preparation for a future change that increases this.
We additionally update the VMA userland test declarations to implement the same changes there.
Finally, we update the rust code to reference vma->vm_flags on update rather than vma->__vm_flags which has been removed. This is safe for now, albeit it is implicitly performing a const cast.
Once we introduce flag helpers we can improve this more.
No functional change intended.
--- include/linux/mm.h | 24 +++-- include/linux/mm_types.h | 64 ++++++++++++- rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma_internal.h | 150 ++++++++++++++++++++++++------- 4 files changed, 202 insertions(+), 38 deletions(-)
include/linux/mm.h +19 -5
@@ -911,7 +911,8 @@ static inline void vm_flags_init(struct vm_area_struct *vma, vm_flags_t flags) {VM_WARN_ON_ONCE (!pgtable_supports_soft_dirty () && (flags &VM_SOFTDIRTY )); -ACCESS_PRIVATE (vma, __vm_flags) = flags; +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word (&vma->flags, flags); }/*
@@ -931,14 +932,25 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma, vm_flags_t flags) {vma_assert_write_locked (vma); -WRITE_ONCE (ACCESS_PRIVATE (vma, __vm_flags), flags); +/* +* If VMA flags exist beyond the first system word, also clear these. It +* is assumed the write once behaviour is required only for the first +* system word. +*/ +if (NUM_VMA_FLAG_BITS >BITS_PER_LONG ) { +unsigned long *bitmap =ACCESS_PRIVATE (&vma->flags, __vma_flags); + +bitmap_zero (&bitmap[1 ],NUM_VMA_FLAG_BITS -BITS_PER_LONG ); + } + +vma_flags_overwrite_word_once (&vma->flags, flags); }static inline void vm_flags_set (struct vm_area_struct *vma,vm_flags_t flags) {vma_start_write (vma); -ACCESS_PRIVATE (vma, __vm_flags) |= flags; +vma_flags_set_word (&vma->flags, flags); } static inline void vm_flags_clear(struct vm_area_struct *vma,
@@ -946,7 +958,7 @@ static inline void vm_flags_clear(struct vm_area_struct *vma, {VM_WARN_ON_ONCE (!pgtable_supports_soft_dirty () && (flags &VM_SOFTDIRTY ));vma_start_write (vma); -ACCESS_PRIVATE (vma, __vm_flags) &= ~flags; +vma_flags_clear_word (&vma->flags, flags); }/*
@@ -989,12 +1001,14 @@ static inline bool __vma_flag_atomic_valid(struct vm_area_struct *vma,static inline void vma_flag_set_atomic (struct vm_area_struct *vma,vma_flag_t bit) { +unsigned long *bitmap =ACCESS_PRIVATE (&vma->flags, __vma_flags); +/* mmap read lock/VMA read lock must be held. */ if (!rwsem_is_locked (&vma->vm_mm->mmap_lock))vma_assert_locked (vma);if (__vma_flag_atomic_valid (vma, bit)) -set_bit ((__force int )bit, &ACCESS_PRIVATE (vma, __vm_flags)); +set_bit ((__force int )bit, bitmap); }/*
include/linux/mm_types.h +62 -2
91 lines not on this page · raw message
rust/kernel/mm/virt.rs +1 -1
@@ -250,7 +250,7 @@ unsafe fn update_flags(&self, set: vm_flags_t, unset: vm_flags_t) {// SAFETY: This is not a data race: the vma is undergoing initial setup, so it's not yet // shared. Additionally, `VmaNew` is `!Sync`, so it cannot be used to write in parallel. // The caller promises that this does not set the flags to an invalid value. -unsafe { (*self.as_ptr ()).__bindgen_anon_2.__vm_flags = flags }; +unsafe { (*self.as_ptr ()).__bindgen_anon_2.vm_flags = flags }; }/// Set the `VM_MIXEDMAP` flag on this vma.
tools/testing/vma/vma_internal.h +120 -30
190 lines not on this page · raw message
Signature · 1 line
2.51.2
Re: [PATCH v3 4/4] mm: introduce VMA flags bitmap type
Quoted 54 lines · Lorenzo Stoakes
It is useful to transition to using a bitmap for VMA flags so we can avoid running out of flags, especially for 32-bit kernels which are constrained to 32 flags, necessitating some features to be limited to 64-bit kernels only.
By doing so, we remove any constraint on the number of VMA flags moving forwards no matter the platform and can decide in future to extend beyond 64 if required.
We start by declaring an opaque types,
vma_flags_t(which resemblesmm_structflags of typemm_flags_t), setting it to precisely the same size asvm_flags_t, and place it in union withvm_flagsin the VMA declaration.We additionally update struct
vm_area_descequivalently placing the new opaque type in union withvm_flags.This change therefore does not impact the size of struct
vm_area_structor structvm_area_desc.In order for the change to be iterative and to avoid impacting performance, we designate
VM_xxxdeclared bitmap flag values as those which must exist in the first system word of the VMA flags bitmap.We therefore declare
vma_flags_clear_all(),vma_flags_overwrite_word(),vma_flags_overwrite_word(),vma_flags_overwrite_word_once(),vma_flags_set_word()andvma_flags_clear_word()in order to allow us to update the existing vm_flags_*() functions to utilise these helpers.This is a stepping stone towards converting users to the VMA flags bitmap and behaves precisely as before.
By doing this, we can eliminate the existing private
vma->__vm_flagsfield in thevma->vm_flagsunion and replace it with the newly introduced opaque typevma_flags, which we call flags so we refer to the new bitmap field asvma->flags.We update vma_flag_[test, set]_atomic() to account for the change also.
We adapt
vm_flags_reset_once()to only clear those bits above the first system word providing write-once semantics to the first system word (which it is presumed the caller requires - and in all current use cases this is so).As we currently only specify that the VMA flags bitmap size is equal to
BITS_PER_LONGnumber of bits, this is a noop, but is defensive in preparation for a future change that increases this.We additionally update the VMA userland test declarations to implement the same changes there.
Finally, we update the rust code to reference
vma->vm_flagson update rather thanvma->__vm_flagswhich has been removed. This is safe for now, albeit it is implicitly performing a const cast.
Quoted 6 lines
Once we introduce flag helpers we can improve this more.
No functional change intended.
Signed-off-by Lorenzo Stoakes <[email protected]>Acked-by Vlastimil Babka <[email protected]>
FWIW, I'm not a huge fan of this vma_flags vs vm_flags and hope we can get rid of this ASAP. But it's a necessary evil for now, anyway.
Signature · 1 line
Pedro
Quoted 33 lines · Lorenzo Stoakes
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
This is necessarily a highly iterative process given the extensive use of VMA flags throughout the kernel, so we start by performing basic steps.
Firstly, we declare VMA flags by bit number rather than by value, retaining the
VM_xxxfields but in terms of these newly introducedVMA_xxx_BITfields.While we are here, we use sparse annotations to ensure that, when dealing with VMA bit number parameters, we cannot be passed values which are not declared as such - providing some useful type safety.
We then introduce an opaque VMA flag type, much like the opaque
mm_structflag type introduced in commitbb6525f2f8c4("mm: add bitmapmm->flagsfield"), which we establish in union withvma->vm_flags(but still set at system word size meaning there is no functional or data type size change).
Quoted 5 lines
We update the
vm_flags_xxx()helpers to use this new bitmap, introducing sensible helpers to do so.This series lays the foundation for further work to expand the use of bitmap VMA flags and eventually eliminate these arbitrary restrictions.
LGTM from Rust perspective.
Quoted 37 lines · Alice Ryhl
Quoted 36 lines · Lorenzo Stoakes
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
This is necessarily a highly iterative process given the extensive use of VMA flags throughout the kernel, so we start by performing basic steps.
Firstly, we declare VMA flags by bit number rather than by value, retaining the
VM_xxxfields but in terms of these newly introducedVMA_xxx_BITfields.While we are here, we use sparse annotations to ensure that, when dealing with VMA bit number parameters, we cannot be passed values which are not declared as such - providing some useful type safety.
We then introduce an opaque VMA flag type, much like the opaque
mm_structflag type introduced in commitbb6525f2f8c4("mm: add bitmapmm->flagsfield"), which we establish in union withvma->vm_flags(but still set at system word size meaning there is no functional or data type size change).We update the
vm_flags_xxx()helpers to use this new bitmap, introducing sensible helpers to do so.
Quoted 6 lines
Quoted 2 lines
This series lays the foundation for further work to expand the use of bitmap VMA flags and eventually eliminate these arbitrary restrictions.
LGTM from Rust perspective.
Acked-by Alice Ryhl <[email protected]>
Thanks! :)
Andrew Morton
maintainerQuoted 10 lines · On Tue, 25 Nov 2025 10:00:58 +0000 Lorenzo Stoakes…
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
Quoted 6 lines
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
All added to mm-unstable, thanks.