diff options
author | Harvey Harrison <harvey.harrison@gmail.com> | 2008-01-30 07:31:10 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:10 -0500 |
commit | 675a0813609f9097e323261b1cc4b9dc3f50d40b (patch) | |
tree | cb23f505f2e2d8a0f9b982ffa7c63858052cf036 /arch/x86/mm | |
parent | f3f20de87c03a90add5e34806c28a03a0d60bde0 (diff) |
x86: unify mmap_{32|64}.c
mmap_is_ia32 always true for X86_32, or while emulating IA32 on X86_64
Randomization not supported on X86_32 in legacy layout. Both layouts allow
randomization on X86_64.
Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/Makefile_32 | 2 | ||||
-rw-r--r-- | arch/x86/mm/Makefile_64 | 3 | ||||
-rw-r--r-- | arch/x86/mm/mmap.c (renamed from arch/x86/mm/mmap_64.c) | 95 | ||||
-rw-r--r-- | arch/x86/mm/mmap_32.c | 81 |
4 files changed, 53 insertions, 128 deletions
diff --git a/arch/x86/mm/Makefile_32 b/arch/x86/mm/Makefile_32 index 362b4ad082de..a01aca79dc69 100644 --- a/arch/x86/mm/Makefile_32 +++ b/arch/x86/mm/Makefile_32 | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the linux i386-specific parts of the memory manager. | 2 | # Makefile for the linux i386-specific parts of the memory manager. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := init_32.o pgtable_32.o fault_32.o ioremap_32.o extable_32.o pageattr_32.o mmap_32.o | 5 | obj-y := init_32.o pgtable_32.o fault_32.o ioremap_32.o extable_32.o pageattr_32.o mmap.o |
6 | 6 | ||
7 | obj-$(CONFIG_NUMA) += discontig_32.o | 7 | obj-$(CONFIG_NUMA) += discontig_32.o |
8 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 8 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
diff --git a/arch/x86/mm/Makefile_64 b/arch/x86/mm/Makefile_64 index d18baed54fc6..b5a74486c3aa 100644 --- a/arch/x86/mm/Makefile_64 +++ b/arch/x86/mm/Makefile_64 | |||
@@ -2,9 +2,8 @@ | |||
2 | # Makefile for the linux x86_64-specific parts of the memory manager. | 2 | # Makefile for the linux x86_64-specific parts of the memory manager. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := init_64.o fault_64.o ioremap_64.o extable_64.o pageattr_64.o mmap_64.o | 5 | obj-y := init_64.o fault_64.o ioremap_64.o extable_64.o pageattr_64.o mmap.o |
6 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 6 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
7 | obj-$(CONFIG_NUMA) += numa_64.o | 7 | obj-$(CONFIG_NUMA) += numa_64.o |
8 | obj-$(CONFIG_K8_NUMA) += k8topology_64.o | 8 | obj-$(CONFIG_K8_NUMA) += k8topology_64.o |
9 | obj-$(CONFIG_ACPI_NUMA) += srat_64.o | 9 | obj-$(CONFIG_ACPI_NUMA) += srat_64.o |
10 | obj-$(CONFIG_IA32_EMULATION) += mmap_32.o | ||
diff --git a/arch/x86/mm/mmap_64.c b/arch/x86/mm/mmap.c index 119bf34ec529..56fe7124fbec 100644 --- a/arch/x86/mm/mmap_64.c +++ b/arch/x86/mm/mmap.c | |||
@@ -1,7 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86-64/mm/mmap.c | 2 | * Flexible mmap layout support |
3 | * | ||
4 | * flexible mmap layout support | ||
5 | * | 3 | * |
6 | * Based on code by Ingo Molnar and Andi Kleen, copyrighted | 4 | * Based on code by Ingo Molnar and Andi Kleen, copyrighted |
7 | * as follows: | 5 | * as follows: |
@@ -24,7 +22,6 @@ | |||
24 | * You should have received a copy of the GNU General Public License | 22 | * You should have received a copy of the GNU General Public License |
25 | * along with this program; if not, write to the Free Software | 23 | * along with this program; if not, write to the Free Software |
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
27 | * | ||
28 | */ | 25 | */ |
29 | 26 | ||
30 | #include <linux/personality.h> | 27 | #include <linux/personality.h> |
@@ -32,7 +29,6 @@ | |||
32 | #include <linux/random.h> | 29 | #include <linux/random.h> |
33 | #include <linux/limits.h> | 30 | #include <linux/limits.h> |
34 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
35 | #include <asm/ia32.h> | ||
36 | 32 | ||
37 | /* | 33 | /* |
38 | * Top of mmap area (just below the process stack). | 34 | * Top of mmap area (just below the process stack). |
@@ -42,20 +38,14 @@ | |||
42 | #define MIN_GAP (128*1024*1024) | 38 | #define MIN_GAP (128*1024*1024) |
43 | #define MAX_GAP (TASK_SIZE/6*5) | 39 | #define MAX_GAP (TASK_SIZE/6*5) |
44 | 40 | ||
45 | static unsigned long mmap_base(void) | 41 | /* |
46 | { | 42 | * True on X86_32 or when emulating IA32 on X86_64 |
47 | unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; | 43 | */ |
48 | 44 | static int mmap_is_ia32(void) | |
49 | if (gap < MIN_GAP) | ||
50 | gap = MIN_GAP; | ||
51 | else if (gap > MAX_GAP) | ||
52 | gap = MAX_GAP; | ||
53 | |||
54 | return TASK_SIZE - (gap & PAGE_MASK); | ||
55 | } | ||
56 | |||
57 | static int mmap_is_32(void) | ||
58 | { | 45 | { |
46 | #ifdef CONFIG_X86_32 | ||
47 | return 1; | ||
48 | #endif | ||
59 | #ifdef CONFIG_IA32_EMULATION | 49 | #ifdef CONFIG_IA32_EMULATION |
60 | if (test_thread_flag(TIF_IA32)) | 50 | if (test_thread_flag(TIF_IA32)) |
61 | return 1; | 51 | return 1; |
@@ -74,43 +64,60 @@ static int mmap_is_legacy(void) | |||
74 | return sysctl_legacy_va_layout; | 64 | return sysctl_legacy_va_layout; |
75 | } | 65 | } |
76 | 66 | ||
67 | static unsigned long mmap_rnd(void) | ||
68 | { | ||
69 | unsigned long rnd = 0; | ||
70 | |||
71 | /* | ||
72 | * 8 bits of randomness in 32bit mmaps, 20 address space bits | ||
73 | * 28 bits of randomness in 64bit mmaps, 40 address space bits | ||
74 | */ | ||
75 | if (current->flags & PF_RANDOMIZE) { | ||
76 | if (mmap_is_ia32()) | ||
77 | rnd = (long)get_random_int() % (1<<8); | ||
78 | else | ||
79 | rnd = (long)(get_random_int() % (1<<28)); | ||
80 | } | ||
81 | return rnd << PAGE_SHIFT; | ||
82 | } | ||
83 | |||
84 | static unsigned long mmap_base(void) | ||
85 | { | ||
86 | unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; | ||
87 | |||
88 | if (gap < MIN_GAP) | ||
89 | gap = MIN_GAP; | ||
90 | else if (gap > MAX_GAP) | ||
91 | gap = MAX_GAP; | ||
92 | |||
93 | return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd()); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 | ||
98 | * does, but not when emulating X86_32 | ||
99 | */ | ||
100 | static unsigned long mmap_legacy_base(void) | ||
101 | { | ||
102 | if (mmap_is_ia32()) | ||
103 | return TASK_UNMAPPED_BASE; | ||
104 | else | ||
105 | return TASK_UNMAPPED_BASE + mmap_rnd(); | ||
106 | } | ||
107 | |||
77 | /* | 108 | /* |
78 | * This function, called very early during the creation of a new | 109 | * This function, called very early during the creation of a new |
79 | * process VM image, sets up which VM layout function to use: | 110 | * process VM image, sets up which VM layout function to use: |
80 | */ | 111 | */ |
81 | void arch_pick_mmap_layout(struct mm_struct *mm) | 112 | void arch_pick_mmap_layout(struct mm_struct *mm) |
82 | { | 113 | { |
83 | int rnd = 0; | 114 | if (mmap_is_legacy()) { |
84 | if (current->flags & PF_RANDOMIZE) { | 115 | mm->mmap_base = mmap_legacy_base(); |
85 | /* | ||
86 | * Add 28bit randomness which is about 40bits of address space | ||
87 | * because mmap base has to be page aligned. | ||
88 | * or ~1/128 of the total user VM | ||
89 | * (total user address space is 47bits) | ||
90 | */ | ||
91 | rnd = get_random_int() & 0xfffffff; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Fall back to the standard layout if the personality | ||
96 | * bit is set, or if the expected stack growth is unlimited: | ||
97 | */ | ||
98 | if (mmap_is_32()) { | ||
99 | #ifdef CONFIG_IA32_EMULATION | ||
100 | /* ia32_pick_mmap_layout has its own. */ | ||
101 | return ia32_pick_mmap_layout(mm); | ||
102 | #endif | ||
103 | } else if (mmap_is_legacy()) { | ||
104 | mm->mmap_base = TASK_UNMAPPED_BASE; | ||
105 | mm->get_unmapped_area = arch_get_unmapped_area; | 116 | mm->get_unmapped_area = arch_get_unmapped_area; |
106 | mm->unmap_area = arch_unmap_area; | 117 | mm->unmap_area = arch_unmap_area; |
107 | } else { | 118 | } else { |
108 | mm->mmap_base = mmap_base(); | 119 | mm->mmap_base = mmap_base(); |
109 | mm->get_unmapped_area = arch_get_unmapped_area_topdown; | 120 | mm->get_unmapped_area = arch_get_unmapped_area_topdown; |
110 | mm->unmap_area = arch_unmap_area_topdown; | 121 | mm->unmap_area = arch_unmap_area_topdown; |
111 | if (current->flags & PF_RANDOMIZE) | ||
112 | rnd = -rnd; | ||
113 | } | 122 | } |
114 | if (current->flags & PF_RANDOMIZE) | ||
115 | mm->mmap_base += ((long)rnd) << PAGE_SHIFT; | ||
116 | } | 123 | } |
diff --git a/arch/x86/mm/mmap_32.c b/arch/x86/mm/mmap_32.c deleted file mode 100644 index d490662e4af4..000000000000 --- a/arch/x86/mm/mmap_32.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
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 | |||
40 | static 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 | */ | ||
60 | #ifdef CONFIG_X86_32 | ||
61 | void arch_pick_mmap_layout(struct mm_struct *mm) | ||
62 | #else | ||
63 | void ia32_pick_mmap_layout(struct mm_struct *mm) | ||
64 | #endif | ||
65 | { | ||
66 | /* | ||
67 | * Fall back to the standard layout if the personality | ||
68 | * bit is set, or if the expected stack growth is unlimited: | ||
69 | */ | ||
70 | if (sysctl_legacy_va_layout || | ||
71 | (current->personality & ADDR_COMPAT_LAYOUT) || | ||
72 | current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { | ||
73 | mm->mmap_base = TASK_UNMAPPED_BASE; | ||
74 | mm->get_unmapped_area = arch_get_unmapped_area; | ||
75 | mm->unmap_area = arch_unmap_area; | ||
76 | } else { | ||
77 | mm->mmap_base = mmap_base(mm); | ||
78 | mm->get_unmapped_area = arch_get_unmapped_area_topdown; | ||
79 | mm->unmap_area = arch_unmap_area_topdown; | ||
80 | } | ||
81 | } | ||