1/* 2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 * 14 * Taken from the i386 architecture and simplified. 15 */ 16 17#include <linux/mm.h> 18#include <linux/random.h> 19#include <linux/limits.h> 20#include <linux/sched.h> 21#include <linux/mman.h> 22#include <linux/compat.h> 23 24/* 25 * Top of mmap area (just below the process stack). 26 * 27 * Leave an at least ~128 MB hole. 28 */ 29#define MIN_GAP (128*1024*1024) 30#define MAX_GAP (TASK_SIZE/6*5) 31 32static inline unsigned long mmap_base(struct mm_struct *mm) 33{ 34 unsigned long gap = rlimit(RLIMIT_STACK); 35 unsigned long random_factor = 0; 36 37 if (current->flags & PF_RANDOMIZE) 38 random_factor = get_random_int() % (1024*1024); 39 40 if (gap < MIN_GAP) 41 gap = MIN_GAP; 42 else if (gap > MAX_GAP) 43 gap = MAX_GAP; 44 45 return PAGE_ALIGN(TASK_SIZE - gap - random_factor); 46} 47 48/* 49 * This function, called very early during the creation of a new 50 * process VM image, sets up which VM layout function to use: 51 */ 52void arch_pick_mmap_layout(struct mm_struct *mm) 53{ 54#if !defined(__tilegx__) 55 int is_32bit = 1; 56#elif defined(CONFIG_COMPAT) 57 int is_32bit = is_compat_task(); 58#else 59 int is_32bit = 0; 60#endif 61 62 /* 63 * Use standard layout if the expected stack growth is unlimited 64 * or we are running native 64 bits. 65 */ 66 if (!is_32bit || rlimit(RLIMIT_STACK) == RLIM_INFINITY) { 67 mm->mmap_base = TASK_UNMAPPED_BASE; 68 mm->get_unmapped_area = arch_get_unmapped_area; 69 mm->unmap_area = arch_unmap_area; 70 } else { 71 mm->mmap_base = mmap_base(mm); 72 mm->get_unmapped_area = arch_get_unmapped_area_topdown; 73 mm->unmap_area = arch_unmap_area_topdown; 74 } 75} 76