1/* 2 * linux/arch/x86_64/ia32/mm/mmap.c 3 * 4 * flexible mmap layout support 5 * 6 * Based on the i386 version which was 7 * 8 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 9 * All Rights Reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 * 26 * Started by Ingo Molnar <mingo@elte.hu> 27 */ 28 29#include <linux/personality.h> 30#include <linux/mm.h> 31#include <linux/random.h> 32#include <linux/sched.h> 33 34/* 35 * Top of mmap area (just below the process stack). 36 * 37 * Leave an at least ~128 MB hole. 38 */ 39#define MIN_GAP (128*1024*1024) 40#define MAX_GAP (TASK_SIZE/6*5) 41 42static inline unsigned long mmap_base(struct mm_struct *mm) 43{ 44 unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; 45 unsigned long random_factor = 0; 46 47 if (current->flags & PF_RANDOMIZE) 48 random_factor = get_random_int() % (1024*1024); 49 50 if (gap < MIN_GAP) 51 gap = MIN_GAP; 52 else if (gap > MAX_GAP) 53 gap = MAX_GAP; 54 55 return PAGE_ALIGN(TASK_SIZE - gap - random_factor); 56} 57 58/* 59 * This function, called very early during the creation of a new 60 * process VM image, sets up which VM layout function to use: 61 */ 62void ia32_pick_mmap_layout(struct mm_struct *mm) 63{ 64 /* 65 * Fall back to the standard layout if the personality 66 * bit is set, or if the expected stack growth is unlimited: 67 */ 68 if (sysctl_legacy_va_layout || 69 (current->personality & ADDR_COMPAT_LAYOUT) || 70 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { 71 mm->mmap_base = TASK_UNMAPPED_BASE; 72 mm->get_unmapped_area = arch_get_unmapped_area; 73 mm->unmap_area = arch_unmap_area; 74 } else { 75 mm->mmap_base = mmap_base(mm); 76 mm->get_unmapped_area = arch_get_unmapped_area_topdown; 77 mm->unmap_area = arch_unmap_area_topdown; 78 } 79} 80