2023-07-12 14:40:04

by Kefeng Wang

[permalink] [raw]
Subject: [PATCH 0/5] mm: convert to vma_is_heap/stack()

Add vma_is_stack() and vma_is_heap() helper and use them to
simplify code.

Kefeng Wang (5):
mm: introduce vma_is_stack() and vma_is_heap()
mm: use vma_is_stack() and vma_is_heap()
drm/amdkfd: use vma_is_stack() and vma_is_heap()
selinux: use vma_is_stack() and vma_is_heap()
perf/core: use vma_is_stack() and vma_is_heap()

drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 5 +----
fs/proc/task_mmu.c | 24 ++++--------------------
fs/proc/task_nommu.c | 15 +--------------
include/linux/mm.h | 12 ++++++++++++
kernel/events/core.c | 22 +++++++---------------
security/selinux/hooks.c | 7 ++-----
6 files changed, 27 insertions(+), 58 deletions(-)

--
2.41.0



2023-07-12 14:45:44

by Kefeng Wang

[permalink] [raw]
Subject: [PATCH 3/5] drm/amdkfd: use vma_is_stack() and vma_is_heap()

Use the helpers to simplify code.

Signed-off-by: Kefeng Wang <[email protected]>
---
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 479c4f66afa7..19ce68a7e1a8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -2623,10 +2623,7 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
return -EFAULT;
}

- *is_heap_stack = (vma->vm_start <= vma->vm_mm->brk &&
- vma->vm_end >= vma->vm_mm->start_brk) ||
- (vma->vm_start <= vma->vm_mm->start_stack &&
- vma->vm_end >= vma->vm_mm->start_stack);
+ *is_heap_stack = vma_is_heap(vma) || vma_is_stack(vma);

start_limit = max(vma->vm_start >> PAGE_SHIFT,
(unsigned long)ALIGN_DOWN(addr, 2UL << 8));
--
2.41.0


2023-07-12 14:47:17

by Kefeng Wang

[permalink] [raw]
Subject: [PATCH 1/5] mm: introduce vma_is_stack() and vma_is_heap()

Introduce the two helpers for general use.

Signed-off-by: Kefeng Wang <[email protected]>
---
include/linux/mm.h | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1462cf15badf..0bbeb31ac750 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -926,6 +926,18 @@ static inline bool vma_is_anonymous(struct vm_area_struct *vma)
return !vma->vm_ops;
}

+static inline bool vma_is_heap(struct vm_area_struct *vma)
+{
+ return vma->vm_start <= vma->vm_mm->brk &&
+ vma->vm_end >= vma->vm_mm->start_brk;
+}
+
+static inline bool vma_is_stack(struct vm_area_struct *vma)
+{
+ return vma->vm_start <= vma->vm_mm->start_stack &&
+ vma->vm_end >= vma->vm_mm->start_stack;
+}
+
static inline bool vma_is_temporary_stack(struct vm_area_struct *vma)
{
int maybe_stack = vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP);
--
2.41.0


2023-07-12 14:52:18

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 3/5] drm/amdkfd: use vma_is_stack() and vma_is_heap()

On Wed, Jul 12, 2023 at 10:38:29PM +0800, Kefeng Wang wrote:
> Use the helpers to simplify code.

Nothing against your addition of a helper, but a GPU driver really
should have no business even looking at this information..


2023-07-12 16:37:18

by Felix Kuehling

[permalink] [raw]
Subject: Re: [PATCH 3/5] drm/amdkfd: use vma_is_stack() and vma_is_heap()

Allocations in the heap and stack tend to be small, with several
allocations sharing the same page. Sharing the same page for different
allocations with different access patterns leads to thrashing when we
migrate data back and forth on GPU and CPU access. To avoid this we
disable HMM migrations for head and stack VMAs.

Regards,
  Felix


Am 2023-07-12 um 10:42 schrieb Christoph Hellwig:
> On Wed, Jul 12, 2023 at 10:38:29PM +0800, Kefeng Wang wrote:
>> Use the helpers to simplify code.
> Nothing against your addition of a helper, but a GPU driver really
> should have no business even looking at this information..
>
>

2023-07-14 14:47:03

by Vlastimil Babka

[permalink] [raw]
Subject: Re: [PATCH 3/5] drm/amdkfd: use vma_is_stack() and vma_is_heap()

On 7/12/23 18:24, Felix Kuehling wrote:
> Allocations in the heap and stack tend to be small, with several
> allocations sharing the same page. Sharing the same page for different
> allocations with different access patterns leads to thrashing when we
> migrate data back and forth on GPU and CPU access. To avoid this we
> disable HMM migrations for head and stack VMAs.

Wonder how well does it really work in practice? AFAIK "heaps" (malloc())
today uses various arenas obtained by mmap() and not a single brk() managed
space anymore? And programs might be multithreaded, thus have multiple
stacks, while vma_is_stack() will recognize only the initial one...

Vlastimil

> Regards,
>   Felix
>
>
> Am 2023-07-12 um 10:42 schrieb Christoph Hellwig:
>> On Wed, Jul 12, 2023 at 10:38:29PM +0800, Kefeng Wang wrote:
>>> Use the helpers to simplify code.
>> Nothing against your addition of a helper, but a GPU driver really
>> should have no business even looking at this information..
>>
>>
>


2023-07-14 15:35:42

by Felix Kuehling

[permalink] [raw]
Subject: Re: [PATCH 3/5] drm/amdkfd: use vma_is_stack() and vma_is_heap()

Am 2023-07-14 um 10:26 schrieb Vlastimil Babka:
> On 7/12/23 18:24, Felix Kuehling wrote:
>> Allocations in the heap and stack tend to be small, with several
>> allocations sharing the same page. Sharing the same page for different
>> allocations with different access patterns leads to thrashing when we
>> migrate data back and forth on GPU and CPU access. To avoid this we
>> disable HMM migrations for head and stack VMAs.
> Wonder how well does it really work in practice? AFAIK "heaps" (malloc())
> today uses various arenas obtained by mmap() and not a single brk() managed
> space anymore? And programs might be multithreaded, thus have multiple
> stacks, while vma_is_stack() will recognize only the initial one...

Thanks for these pointers. I have not heard of such problems with mmap
arenas and multiple thread stacks in practice. But I'll keep it in mind
in case we observe unexpected thrashing in the future. FWIW, we once had
the opposite problem of a custom malloc implementation that used sbrk
for very large allocations. This disabled migrations of large buffers
unexpectedly.

I agree that eventually we'll want a more dynamic way of detecting and
suppressing thrashing that's based on observed memory access patterns.
Getting this right is probably trickier than it sounds, so I'd prefer to
have some more experience with real workloads to use as benchmarks.
Compared to other things we're working on, this is fairly low on our
priority list at the moment. Using the VMA flags is a simple and
effective method for now, at least until we see it failing in real
workloads.

Regards,
  Felix


>
> Vlastimil
>
>> Regards,
>>   Felix
>>
>>
>> Am 2023-07-12 um 10:42 schrieb Christoph Hellwig:
>>> On Wed, Jul 12, 2023 at 10:38:29PM +0800, Kefeng Wang wrote:
>>>> Use the helpers to simplify code.
>>> Nothing against your addition of a helper, but a GPU driver really
>>> should have no business even looking at this information..
>>>
>>>

2023-07-17 10:36:55

by David Hildenbrand

[permalink] [raw]
Subject: Re: [PATCH 1/5] mm: introduce vma_is_stack() and vma_is_heap()

On 12.07.23 16:38, Kefeng Wang wrote:
> Introduce the two helpers for general use.
>
> Signed-off-by: Kefeng Wang <[email protected]>
> ---
> include/linux/mm.h | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 1462cf15badf..0bbeb31ac750 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -926,6 +926,18 @@ static inline bool vma_is_anonymous(struct vm_area_struct *vma)
> return !vma->vm_ops;
> }
>
> +static inline bool vma_is_heap(struct vm_area_struct *vma)
> +{
> + return vma->vm_start <= vma->vm_mm->brk &&
> + vma->vm_end >= vma->vm_mm->start_brk;
> +}
> +
> +static inline bool vma_is_stack(struct vm_area_struct *vma)
> +{
> + return vma->vm_start <= vma->vm_mm->start_stack &&
> + vma->vm_end >= vma->vm_mm->start_stack;
> +}
> +
> static inline bool vma_is_temporary_stack(struct vm_area_struct *vma)
> {
> int maybe_stack = vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP);

Looking at the comments in patch #3, should these functions be called

vma_is_initial_heap / vma_is_initial_stack ?

--
Cheers,

David / dhildenb


2023-07-18 15:30:15

by Christian Göttsche

[permalink] [raw]
Subject: Re: [PATCH 1/5] mm: introduce vma_is_stack() and vma_is_heap()

On Wed, 12 Jul 2023 at 16:25, Kefeng Wang <[email protected]> wrote:
>
> Introduce the two helpers for general use.
>
> Signed-off-by: Kefeng Wang <[email protected]>
> ---
> include/linux/mm.h | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 1462cf15badf..0bbeb31ac750 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -926,6 +926,18 @@ static inline bool vma_is_anonymous(struct vm_area_struct *vma)
> return !vma->vm_ops;
> }
>
> +static inline bool vma_is_heap(struct vm_area_struct *vma)

What about declaring the parameters const to document in code these
functions do not modify any state, and allow callers to pass pointers
to const?

> +{
> + return vma->vm_start <= vma->vm_mm->brk &&
> + vma->vm_end >= vma->vm_mm->start_brk;
> +}
> +
> +static inline bool vma_is_stack(struct vm_area_struct *vma)
> +{
> + return vma->vm_start <= vma->vm_mm->start_stack &&
> + vma->vm_end >= vma->vm_mm->start_stack;
> +}
> +
> static inline bool vma_is_temporary_stack(struct vm_area_struct *vma)
> {
> int maybe_stack = vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP);
> --
> 2.41.0
>