On Sat, May 30, 2026 at 07:52:25PM +0300, Mike Rapoport wrote: > On Fri, May 29, 2026 at 03:00:14PM +0100, Lorenzo Stoakes wrote: > > On Tue, May 26, 2026 at 02:04:52PM +0100, Kiryl Shutsemau wrote: > > > From: "Kiryl Shutsemau (Meta)" <[email protected]> > > > > > > vma_flags_t is one unsigned long on 32-bit -- NUM_VMA_FLAG_BITS == > > > BITS_PER_LONG by design, so VM_xxx-declared bits sit in the first > > > word and hit the single-long fast path. But the bit enum declares > > > some bits unconditionally above BITS_PER_LONG (VMA_UFFD_MINOR_BIT > > > == 41 today, with VM_UFFD_MINOR == VM_NONE on 32-bit so no VMA > > > actually carries the bit). > > > > Yeah ugh. > > > > > Passing such a bit to mk_vma_flags() goes through __set_bit(41, > > > &one_long) and writes one word past the end. The compiler folds > > > the OOB store with wraparound (1UL << (41 % 32) == bit 9) into > > > the first word. Bit 9 is already in __VMA_UFFD_FLAGS so the mask > > > happens to come out right today, but any high-numbered bit whose > > > > That is... helpful :) but not great that this is the situation, an > > oversight, clearly! How I hate 32-bit kernels :) > > > > > mod-BITS_PER_LONG position is otherwise unused would silently OR > > > an extra bit into the mask. > > > > > > Add VMA_NO_BIT and have DECLARE_VMA_BIT() resolve any bitnum out > > > of range to it. vma_flags_set_flag() drops negative bit values. > > > The ternary collapses at compile time, the runtime check folds > > > away when the bit is in range, and the common path is unchanged. > > > > Hmm are you sure it does? > > > > A key design goal was that mk_vma_flags() generates compile-time constants > > the same as if the bitmap were constructed independently. > > > > This surely must generate code? Or at least runs a significant risk of it? > > ... > > > A simple solution that doesn't require change to the core is to just uglify > > userfaultfd_k.h a bit with: > > > > #ifdef HAVE_ARCH_USERFAULTFD_MINOR > > #define __VMA_UFFD_FLAGS mk_vma_flags(VMA_UFFD_MISSING_BIT, > > VMA_UFFD_WP_BIT, \ > > VMA_UFFD_MINOR_BIT) > > #else > > #define __VMA_UFFD_FLAGS mk_vma_flags(VMA_UFFD_MISSING_BIT, VMA_UFFD_WP_BIT) > > #endif > > > > But of course that becomes much more horrible with your changes... > > > > Another alternative, which I used for VMA_DROPPABLE is to add something > > like this in mm.h: > > > > #ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR > > #define VM_UFFD_MINOR INIT_VM_FLAG(UFFD_MINOR) > > +define VMA_UFFD_MINOR mk_vma_flags(VMA_UFFD_MINOR_BIT) > > #else > > #define VM_UFFD_MINOR VM_NONE > > +define VMA_UFFD_MINOR EMPTY_VMA_FLAGS > > #endif > > I have a PoC of yet another alternative: > > https://git.kernel.org/pub/scm/linux/kernel/git/rppt/linux.git/log/?h=uffd/vm-flags > > The idea there is to keep a single VMA flag, VMA_UFFD_BIT/VM_UFFD and move > all the rest into what's now struct vm_userfaultfd_ctx.
*Gives Mike a big kiss* YES PLEASE! > > -- > Sincerely yours, > Mike. Thanks, Lorenzo

