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 5932a824547a..e008d236cc15 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 |
