| From 3b4d07d2674f6b4a9281031f99d1f7efd325b16d Mon Sep 17 00:00:00 2001 |
| From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> |
| Date: Tue, 26 Feb 2019 10:09:35 +0530 |
| Subject: powerpc/mm/hash: Handle mmap_min_addr correctly in get_unmapped_area topdown search |
| |
| From: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> |
| |
| commit 3b4d07d2674f6b4a9281031f99d1f7efd325b16d upstream. |
| |
| When doing top-down search the low_limit is not PAGE_SIZE but rather |
| max(PAGE_SIZE, mmap_min_addr). This handle cases in which mmap_min_addr > |
| PAGE_SIZE. |
| |
| Fixes: fba2369e6ceb ("mm: use vm_unmapped_area() on powerpc architecture") |
| Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> |
| Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/mm/slice.c | 10 ++++++---- |
| 1 file changed, 6 insertions(+), 4 deletions(-) |
| |
| --- a/arch/powerpc/mm/slice.c |
| +++ b/arch/powerpc/mm/slice.c |
| @@ -32,6 +32,7 @@ |
| #include <linux/export.h> |
| #include <linux/hugetlb.h> |
| #include <linux/sched/mm.h> |
| +#include <linux/security.h> |
| #include <asm/mman.h> |
| #include <asm/mmu.h> |
| #include <asm/copro.h> |
| @@ -377,6 +378,7 @@ static unsigned long slice_find_area_top |
| int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); |
| unsigned long addr, found, prev; |
| struct vm_unmapped_area_info info; |
| + unsigned long min_addr = max(PAGE_SIZE, mmap_min_addr); |
| |
| info.flags = VM_UNMAPPED_AREA_TOPDOWN; |
| info.length = len; |
| @@ -393,7 +395,7 @@ static unsigned long slice_find_area_top |
| if (high_limit > DEFAULT_MAP_WINDOW) |
| addr += mm->context.slb_addr_limit - DEFAULT_MAP_WINDOW; |
| |
| - while (addr > PAGE_SIZE) { |
| + while (addr > min_addr) { |
| info.high_limit = addr; |
| if (!slice_scan_available(addr - 1, available, 0, &addr)) |
| continue; |
| @@ -405,8 +407,8 @@ static unsigned long slice_find_area_top |
| * Check if we need to reduce the range, or if we can |
| * extend it to cover the previous available slice. |
| */ |
| - if (addr < PAGE_SIZE) |
| - addr = PAGE_SIZE; |
| + if (addr < min_addr) |
| + addr = min_addr; |
| else if (slice_scan_available(addr - 1, available, 0, &prev)) { |
| addr = prev; |
| goto prev_slice; |
| @@ -528,7 +530,7 @@ unsigned long slice_get_unmapped_area(un |
| addr = _ALIGN_UP(addr, page_size); |
| slice_dbg(" aligned addr=%lx\n", addr); |
| /* Ignore hint if it's too large or overlaps a VMA */ |
| - if (addr > high_limit - len || |
| + if (addr > high_limit - len || addr < mmap_min_addr || |
| !slice_area_is_free(mm, addr, len)) |
| addr = 0; |
| } |