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