diff options
Diffstat (limited to 'arch/s390/mm/mmap.c')
-rw-r--r-- | arch/s390/mm/mmap.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 5932a824547..e008d236cc1 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c | |||
@@ -35,7 +35,7 @@ | |||
35 | * Leave an at least ~128 MB hole. | 35 | * Leave an at least ~128 MB hole. |
36 | */ | 36 | */ |
37 | #define MIN_GAP (128*1024*1024) | 37 | #define MIN_GAP (128*1024*1024) |
38 | #define MAX_GAP (TASK_SIZE/6*5) | 38 | #define MAX_GAP (STACK_TOP/6*5) |
39 | 39 | ||
40 | static inline unsigned long mmap_base(void) | 40 | static inline unsigned long mmap_base(void) |
41 | { | 41 | { |
@@ -46,7 +46,7 @@ static inline unsigned long mmap_base(void) | |||
46 | else if (gap > MAX_GAP) | 46 | else if (gap > MAX_GAP) |
47 | gap = MAX_GAP; | 47 | gap = MAX_GAP; |
48 | 48 | ||
49 | return TASK_SIZE - (gap & PAGE_MASK); | 49 | return STACK_TOP - (gap & PAGE_MASK); |
50 | } | 50 | } |
51 | 51 | ||
52 | static inline int mmap_is_legacy(void) | 52 | static inline int mmap_is_legacy(void) |
@@ -89,42 +89,58 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout); | |||
89 | 89 | ||
90 | #else | 90 | #else |
91 | 91 | ||
92 | int s390_mmap_check(unsigned long addr, unsigned long len) | ||
93 | { | ||
94 | if (!test_thread_flag(TIF_31BIT) && | ||
95 | len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) | ||
96 | return crst_table_upgrade(current->mm, 1UL << 53); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
92 | static unsigned long | 100 | static unsigned long |
93 | s390_get_unmapped_area(struct file *filp, unsigned long addr, | 101 | s390_get_unmapped_area(struct file *filp, unsigned long addr, |
94 | unsigned long len, unsigned long pgoff, unsigned long flags) | 102 | unsigned long len, unsigned long pgoff, unsigned long flags) |
95 | { | 103 | { |
96 | struct mm_struct *mm = current->mm; | 104 | struct mm_struct *mm = current->mm; |
105 | unsigned long area; | ||
97 | int rc; | 106 | int rc; |
98 | 107 | ||
99 | addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags); | 108 | area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); |
100 | if (addr & ~PAGE_MASK) | 109 | if (!(area & ~PAGE_MASK)) |
101 | return addr; | 110 | return area; |
102 | if (unlikely(mm->context.asce_limit < addr + len)) { | 111 | if (area == -ENOMEM && |
103 | rc = crst_table_upgrade(mm, addr + len); | 112 | !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) { |
113 | /* Upgrade the page table to 4 levels and retry. */ | ||
114 | rc = crst_table_upgrade(mm, 1UL << 53); | ||
104 | if (rc) | 115 | if (rc) |
105 | return (unsigned long) rc; | 116 | return (unsigned long) rc; |
117 | area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); | ||
106 | } | 118 | } |
107 | return addr; | 119 | return area; |
108 | } | 120 | } |
109 | 121 | ||
110 | static unsigned long | 122 | static unsigned long |
111 | s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, | 123 | s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, |
112 | const unsigned long len, const unsigned long pgoff, | 124 | const unsigned long len, const unsigned long pgoff, |
113 | const unsigned long flags) | 125 | const unsigned long flags) |
114 | { | 126 | { |
115 | struct mm_struct *mm = current->mm; | 127 | struct mm_struct *mm = current->mm; |
116 | unsigned long addr = addr0; | 128 | unsigned long area; |
117 | int rc; | 129 | int rc; |
118 | 130 | ||
119 | addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); | 131 | area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); |
120 | if (addr & ~PAGE_MASK) | 132 | if (!(area & ~PAGE_MASK)) |
121 | return addr; | 133 | return area; |
122 | if (unlikely(mm->context.asce_limit < addr + len)) { | 134 | if (area == -ENOMEM && |
123 | rc = crst_table_upgrade(mm, addr + len); | 135 | !test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) { |
136 | /* Upgrade the page table to 4 levels and retry. */ | ||
137 | rc = crst_table_upgrade(mm, 1UL << 53); | ||
124 | if (rc) | 138 | if (rc) |
125 | return (unsigned long) rc; | 139 | return (unsigned long) rc; |
140 | area = arch_get_unmapped_area_topdown(filp, addr, len, | ||
141 | pgoff, flags); | ||
126 | } | 142 | } |
127 | return addr; | 143 | return area; |
128 | } | 144 | } |
129 | /* | 145 | /* |
130 | * This function, called very early during the creation of a new | 146 | * This function, called very early during the creation of a new |