diff mbox series

[V2,1/4] mm: mmap: Allow for "high" userspace addresses

Message ID 20181017163459.20175-2-steve.capper@arm.com (mailing list archive)
State New, archived
Headers show
Series 52-bit userspace VAs | expand

Commit Message

Steve Capper Oct. 17, 2018, 4:34 p.m. UTC
This patch adds support for "high" userspace addresses that are
optionally supported on the system and have to be requested via a hint
mechanism ("high" addr parameter to mmap).

Rather than duplicate the arch_get_unmapped_* stock implementations,
this patch instead introduces two architectural helper macros and
applies them to arch_get_unmapped_*:
 arch_get_mmap_end(addr) - get mmap upper limit depending on addr hint
 arch_get_mmap_base(addr, base) - get mmap_base depending on addr hint

If these macros are not defined in architectural code then they default
to (TASK_SIZE) and (base) so should not introduce any behavioural
changes to architectures that do not define them.

Signed-off-by: Steve Capper <steve.capper@arm.com>
---
Changed in V2, these alterations are made to mm/mmap.c rather than
copied over to arch/arm64 and modified there.
---
 mm/mmap.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

Comments

Matthew Wilcox (Oracle) Oct. 17, 2018, 4:48 p.m. UTC | #1
On Wed, Oct 17, 2018 at 05:34:56PM +0100, Steve Capper wrote:
> This patch adds support for "high" userspace addresses that are
> optionally supported on the system and have to be requested via a hint
> mechanism ("high" addr parameter to mmap).
> 
> Rather than duplicate the arch_get_unmapped_* stock implementations,
> this patch instead introduces two architectural helper macros and
> applies them to arch_get_unmapped_*:
>  arch_get_mmap_end(addr) - get mmap upper limit depending on addr hint
>  arch_get_mmap_base(addr, base) - get mmap_base depending on addr hint
> 
> If these macros are not defined in architectural code then they default
> to (TASK_SIZE) and (base) so should not introduce any behavioural
> changes to architectures that do not define them.

Can you explain (in the changelog) why we need to do this for arm64
when it wasn't needed for the equivalent feature on x86-64?  I think the
answer is that x86-64 already has its own arch_get_unmapped* functions and
rather than duplicating arch_get_unmapped* for arm64, you want to continue
using the generic ones with just this minor hooking.  But I'd like that
spelled out explicitly for the next person who comes along and wonders.
Steve Capper Oct. 18, 2018, 10:35 a.m. UTC | #2
On Wed, Oct 17, 2018 at 09:48:15AM -0700, Matthew Wilcox wrote:
> On Wed, Oct 17, 2018 at 05:34:56PM +0100, Steve Capper wrote:
> > This patch adds support for "high" userspace addresses that are
> > optionally supported on the system and have to be requested via a hint
> > mechanism ("high" addr parameter to mmap).
> > 
> > Rather than duplicate the arch_get_unmapped_* stock implementations,
> > this patch instead introduces two architectural helper macros and
> > applies them to arch_get_unmapped_*:
> >  arch_get_mmap_end(addr) - get mmap upper limit depending on addr hint
> >  arch_get_mmap_base(addr, base) - get mmap_base depending on addr hint
> > 
> > If these macros are not defined in architectural code then they default
> > to (TASK_SIZE) and (base) so should not introduce any behavioural
> > changes to architectures that do not define them.
> 
> Can you explain (in the changelog) why we need to do this for arm64
> when it wasn't needed for the equivalent feature on x86-64?  I think the
> answer is that x86-64 already has its own arch_get_unmapped* functions and
> rather than duplicating arch_get_unmapped* for arm64, you want to continue
> using the generic ones with just this minor hooking.  But I'd like that
> spelled out explicitly for the next person who comes along and wonders.
>

Thanks Matthew,
Yes we thought it better to make an unobtrusive change to the generic
code rather than copy it over to arm64 (whilst x86 already had an
architecture specific version that was patched).

I will make the commit log a lot clearer.

Cheers,
diff mbox series

Patch

diff --git a/mm/mmap.c b/mm/mmap.c
index 5f2b2b184c60..396b8ae12783 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2042,6 +2042,15 @@  unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
 	return gap_end;
 }
 
+
+#ifndef arch_get_mmap_end
+#define arch_get_mmap_end(addr)	(TASK_SIZE)
+#endif
+
+#ifndef arch_get_mmap_base
+#define arch_get_mmap_base(addr, base) (base)
+#endif
+
 /* Get an address range which is currently unmapped.
  * For shmat() with addr=0.
  *
@@ -2061,8 +2070,9 @@  arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma, *prev;
 	struct vm_unmapped_area_info info;
+	const unsigned long mmap_end = arch_get_mmap_end(addr);
 
-	if (len > TASK_SIZE - mmap_min_addr)
+	if (len > mmap_end - mmap_min_addr)
 		return -ENOMEM;
 
 	if (flags & MAP_FIXED)
@@ -2071,7 +2081,7 @@  arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma_prev(mm, addr, &prev);
-		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
+		if (mmap_end - len >= addr && addr >= mmap_min_addr &&
 		    (!vma || addr + len <= vm_start_gap(vma)) &&
 		    (!prev || addr >= vm_end_gap(prev)))
 			return addr;
@@ -2080,7 +2090,7 @@  arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	info.flags = 0;
 	info.length = len;
 	info.low_limit = mm->mmap_base;
-	info.high_limit = TASK_SIZE;
+	info.high_limit = mmap_end;
 	info.align_mask = 0;
 	return vm_unmapped_area(&info);
 }
@@ -2100,9 +2110,10 @@  arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	struct mm_struct *mm = current->mm;
 	unsigned long addr = addr0;
 	struct vm_unmapped_area_info info;
+	const unsigned long mmap_end = arch_get_mmap_end(addr);
 
 	/* requested length too big for entire address space */
-	if (len > TASK_SIZE - mmap_min_addr)
+	if (len > mmap_end - mmap_min_addr)
 		return -ENOMEM;
 
 	if (flags & MAP_FIXED)
@@ -2112,7 +2123,7 @@  arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma_prev(mm, addr, &prev);
-		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
+		if (mmap_end - len >= addr && addr >= mmap_min_addr &&
 				(!vma || addr + len <= vm_start_gap(vma)) &&
 				(!prev || addr >= vm_end_gap(prev)))
 			return addr;
@@ -2121,7 +2132,7 @@  arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
 	info.length = len;
 	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
-	info.high_limit = mm->mmap_base;
+	info.high_limit = arch_get_mmap_base(addr, mm->mmap_base);
 	info.align_mask = 0;
 	addr = vm_unmapped_area(&info);
 
@@ -2135,7 +2146,7 @@  arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 		VM_BUG_ON(addr != -ENOMEM);
 		info.flags = 0;
 		info.low_limit = TASK_UNMAPPED_BASE;
-		info.high_limit = TASK_SIZE;
+		info.high_limit = mmap_end;
 		addr = vm_unmapped_area(&info);
 	}