* Lorenzo Stoakes <[email protected]> [260122 16:06]:
> This patch introduces the mk_vma_flags() macro helper to allow easy
> manipulation of VMA flags utilising the new bitmap representation
> implemented of VMA flags defined by the vma_flags_t type.
> 
> It is a variadic macro which provides a bitwise-or'd representation of all
> of each individual VMA flag specified.
> 
> Note that, while we maintain VM_xxx flags for backwards compatibility until
> the conversion is complete, we define VMA flags of type vma_flag_t using
> VMA_xxx_BIT to avoid confusing the two.
> 
> This helper macro therefore can be used thusly:
> 
> vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT);
> 
> We allow for up to 5 flags to specified at a time which should accommodate
> all current kernel uses of combined VMA flags.
> 
> Testing has demonstrated that the compiler optimises this code such that it
> generates the same assembly utilising this macro as it does if the flags
> were specified manually, for instance:
> 
> vma_flags_t get_flags(void)
> {
>       return mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
> }
> 
> Generates the same code as:
> 
> vma_flags_t get_flags(void)
> {
>       vma_flags_t flags;
> 
>       vma_flags_clear_all(&flags);
>       vma_flag_set(&flags, VMA_READ_BIT);
>       vma_flag_set(&flags, VMA_WRITE_BIT);
>       vma_flag_set(&flags, VMA_EXEC_BIT);
> 
>       return flags;
> }
> 
> And:
> 
> vma_flags_t get_flags(void)
> {
>       vma_flags_t flags;
>       unsigned long *bitmap = ACCESS_PRIVATE(&flags, __vma_flags);
> 
>       *bitmap = 1UL << (__force int)VMA_READ_BIT;
>       *bitmap |= 1UL << (__force int)VMA_WRITE_BIT;
>       *bitmap |= 1UL << (__force int)VMA_EXEC_BIT;
> 
>       return flags;
> }
> 
> That is:
> 
> get_flags:
>         movl    $7, %eax
>         ret
> 
> Suggested-by: Jason Gunthorpe <[email protected]>
> Signed-off-by: Lorenzo Stoakes <[email protected]>

Besides the part about 5 arguments that has been discussed,

Reviewed-by: Liam R. Howlett <[email protected]>

> ---
>  include/linux/mm.h | 33 +++++++++++++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index e0d31238097c..32c3b5347dc6 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -2,6 +2,7 @@
>  #ifndef _LINUX_MM_H
>  #define _LINUX_MM_H
>  
> +#include <linux/args.h>
>  #include <linux/errno.h>
>  #include <linux/mmdebug.h>
>  #include <linux/gfp.h>
> @@ -1026,6 +1027,38 @@ static inline bool vma_test_atomic_flag(struct 
> vm_area_struct *vma, vma_flag_t b
>       return false;
>  }
>  
> +/* Set an individual VMA flag in flags, non-atomically. */
> +static inline void vma_flag_set(vma_flags_t *flags, vma_flag_t bit)
> +{
> +     unsigned long *bitmap = flags->__vma_flags;
> +
> +     __set_bit((__force int)bit, bitmap);
> +}
> +
> +static inline vma_flags_t __mk_vma_flags(size_t count, const vma_flag_t 
> *bits)
> +{
> +     vma_flags_t flags;
> +     int i;
> +
> +     vma_flags_clear_all(&flags);
> +     for (i = 0; i < count; i++)
> +             vma_flag_set(&flags, bits[i]);
> +     return flags;
> +}
> +
> +/*
> + * Helper macro which bitwise-or combines the specified input flags into a
> + * vma_flags_t bitmap value. E.g.:
> + *
> + * vma_flags_t flags = mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT,
> + *           VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT);
> + *
> + * The compiler cleverly optimises away all of the work and this ends up 
> being
> + * equivalent to aggregating the values manually.
> + */
> +#define mk_vma_flags(...) __mk_vma_flags(COUNT_ARGS(__VA_ARGS__), \
> +                                      (const vma_flag_t []){__VA_ARGS__})
> +
>  static inline void vma_set_anonymous(struct vm_area_struct *vma)
>  {
>       vma->vm_ops = NULL;
> -- 
> 2.52.0
> 

Reply via email to