On 10/9/26 20:04, Lorenzo Stoakes (ARM) wrote:
> We have now made it such that every driver which sets VMA_IO_BIT marks it
> as not mm-managed.

Confusing given that mm-managed check tests VMA_IO_BIT.

Maybe combining this with the next paragraph could make this easier to grasp

"vma_flags_is_mm_managed() still checks for VMA_IO_BIT, and if set, treats it as
non-mm-managed. This was previously required to handle driver that would set
VMA_IO_BIT but none of the other flags that would indicate a VMA as 
non-mm-managed.

We already established now that a driver that sets VMA_IO_BIT must set one of
the other VMA flags that allow for identifying it as non-mm-managed.

...
"

> 
> However, vma_flags_is_mm_managed() currently treats VMA_IO_BIT as
> disqualifying. This was a product of drivers previously marking a range as
> not mm-managed by
> setting VMA_IO_BIT alone.
> 
> Fix this by removing the VMA_IO_BIT check in vma_flags_is_mm_managed(),
> and update mmap_validate_vma_flags() to use vma_flags_is_mm_managed()
> rather than open-coding the VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT check.
> 
> This change means that vma[_flags]_can_merge() doesn't check VMA_IO_BIT any
> longer (which is now redundant) as it calls vma_flags_is_mm_managed().
> 
> Now that the predicate means precisely VMA_PFNMAP_BIT or VMA_MIXEDMAP_BIT,
> also use it at the other sites which open-code that pair, so the intent is
> stated rather than the flags, with no functional change:
> 
> zap_special_vma_range() only zaps mappings which are not mm-managed, as
> drivers use it
> to tear down ranges they established themselves.
> 
> The mprotect() arch PFN modification check applies to mappings not managed
> by core mm, which may map PFNs without struct pages.
> 
> NUMA balancing skips VM_MIXEDMAP mappings having already excluded VM_IO
> and VM_PFNMAP mappings via vma_migratable(), so it skips exactly the
> mappings not managed by core mm - say so.
> 
> Finally, update the VMA userland merge 'special' flag tests to no longer
> assert that VMA_IO_BIT prevents merge as VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT
> now suffices.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
> ---
>  include/linux/mm.h              |  3 +--
>  kernel/sched/fair.c             |  2 +-
>  mm/memory.c                     |  7 ++++---
>  mm/mprotect.c                   |  3 +--
>  mm/vma.c                        |  2 +-
>  tools/testing/vma/include/dup.h |  3 +--
>  tools/testing/vma/tests/merge.c | 10 ++--------
>  7 files changed, 11 insertions(+), 19 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 6b5f06cd174a..3ddb463db895 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1627,8 +1627,7 @@ static inline bool vma_is_shared_maywrite(const struct 
> vm_area_struct *vma)
>   */
>  static inline bool vma_flags_is_mm_managed(const vma_flags_t *flags)
>  {
> -     return !vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT,
> -                                VMA_IO_BIT);
> +     return !vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT);
>  }
>  
>  /**
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 8dff37059faf..a07a658cd99f 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -4212,7 +4212,7 @@ static void task_numa_work(struct callback_head *work)
>  
>       for (; vma; vma = vma_next(&vmi)) {
>               if (!vma_migratable(vma) || !vma_policy_mof(vma) ||
> -                     is_vm_hugetlb_page(vma) || (vma->vm_flags & 
> VM_MIXEDMAP)) {
> +                     is_vm_hugetlb_page(vma) || !vma_is_mm_managed(vma)) {
>                       trace_sched_skip_vma_numa(mm, vma, 
> NUMAB_SKIP_UNSUITABLE);
>                       continue;
>               }
> diff --git a/mm/memory.c b/mm/memory.c
> index e5c1d1c35bc7..094983683f24 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -2343,19 +2343,20 @@ void zap_vma_range(struct vm_area_struct *vma, 
> unsigned long address,
>  }
>  
>  /**
> - * zap_special_vma_range - zap all page table entries in a special vma range
> + * zap_special_vma_range - zap all page table entries in a VMA which is not
> + * mm-managed
>   * @vma: the vma covering the range to zap
>   * @address: starting address of the range to zap
>   * @size: number of bytes to zap
>   *
>   * This function does nothing when the provided address range is not fully
> - * contained in @vma, or when the @vma is not VM_PFNMAP or VM_MIXEDMAP.
> + * contained in @vma, or when @vma is mm-managed.
>   */
>  void zap_special_vma_range(struct vm_area_struct *vma, unsigned long address,
>               unsigned long size)
>  {
>       if (!range_in_vma(vma, address, address + size) ||
> -        !(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)))
> +        vma_is_mm_managed(vma))
>               return;
>  
>       zap_vma_range(vma, address, size);
> diff --git a/mm/mprotect.c b/mm/mprotect.c
> index 2888ee638d87..706c679d4281 100644
> --- a/mm/mprotect.c
> +++ b/mm/mprotect.c
> @@ -783,8 +783,7 @@ mprotect_fixup(struct vma_iterator *vmi, struct 
> mmu_gather *tlb,
>        * uncommon case, so doesn't need to be very optimized.
>        */
>       if (arch_has_pfn_modify_check() &&
> -         vma_flags_test_any(&old_vma_flags, VMA_PFNMAP_BIT,
> -                            VMA_MIXEDMAP_BIT) &&
> +         !vma_flags_is_mm_managed(&old_vma_flags) &&
>           !vma_flags_test_any_mask(&new_vma_flags, VMA_ACCESS_FLAGS)) {
>               pgprot_t new_pgprot = vm_get_page_prot(newflags);
>  
> diff --git a/mm/vma.c b/mm/vma.c
> index 51bdbe08bb02..cb8729b195ea 100644
> --- a/mm/vma.c
> +++ b/mm/vma.c
> @@ -2796,7 +2796,7 @@ static int mmap_validate_vma_flags(const vma_flags_t 
> *flags)
>               return -EINVAL;
>  #endif
>  
> -     if (!vma_flags_test_any(flags, VMA_PFNMAP_BIT, VMA_MIXEDMAP_BIT)) {
> +     if (vma_flags_is_mm_managed(flags)) {

Ah, there is the change.

Acked-by: David Hildenbrand (Arm) <[email protected]>

-- 
Cheers,

David

Reply via email to