diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-04-20 14:43:51 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-04-25 07:47:32 +0200 |
commit | ee71d16d22bb268c1f6a64ef6d3654ace5f1e8c7 (patch) | |
tree | 8e8ecc1da0ba8947a9b024a435262460d67caeff /arch/s390/mm | |
parent | 5037c22c53603acd4e8c465d750fdd604c600bd3 (diff) | |
download | linux-ee71d16d22bb268c1f6a64ef6d3654ace5f1e8c7.tar.bz2 |
s390/mm: make TASK_SIZE independent from the number of page table levels
The TASK_SIZE for a process should be maximum possible size of the address
space, 2GB for a 31-bit process and 8PB for a 64-bit process. The number
of page table levels required for a given memory layout is a consequence
of the mapped memory areas and their location.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r-- | arch/s390/mm/gmap.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/gup.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/mmap.c | 31 | ||||
-rw-r--r-- | arch/s390/mm/pgalloc.c | 2 |
4 files changed, 14 insertions, 23 deletions
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index ffb55c935eda..7f6db1e6c048 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -431,7 +431,7 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from, if ((from | to | len) & (PMD_SIZE - 1)) return -EINVAL; if (len == 0 || from + len < from || to + len < to || - from + len - 1 > TASK_MAX_SIZE || to + len - 1 > gmap->asce_end) + from + len - 1 > TASK_SIZE_MAX || to + len - 1 > gmap->asce_end) return -EINVAL; flush = 0; diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 18d4107e10ee..b7b779c40a5b 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -211,7 +211,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if ((end <= start) || (end > TASK_SIZE)) + if ((end <= start) || (end > mm->context.asce_limit)) return 0; /* * local_irq_save() doesn't prevent pagetable teardown, but does diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 50618614881f..eed233ce59dd 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -90,7 +90,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma; struct vm_unmapped_area_info info; - if (len > TASK_SIZE - mmap_min_addr) + if (len > mm->context.asce_limit - mmap_min_addr) return -ENOMEM; if (flags & MAP_FIXED) @@ -99,7 +99,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && + if (mm->context.asce_limit - len >= addr && + addr >= mmap_min_addr && (!vma || addr + len <= vma->vm_start)) return addr; } @@ -107,7 +108,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, info.flags = 0; info.length = len; info.low_limit = mm->mmap_base; - info.high_limit = TASK_SIZE; + info.high_limit = mm->context.asce_limit; if (filp || (flags & MAP_SHARED)) info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT; else @@ -127,7 +128,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, struct vm_unmapped_area_info info; /* requested length too big for entire address space */ - if (len > TASK_SIZE - mmap_min_addr) + if (len > mm->context.asce_limit - mmap_min_addr) return -ENOMEM; if (flags & MAP_FIXED) @@ -137,7 +138,8 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && + if (mm->context.asce_limit - len >= addr && + addr >= mmap_min_addr && (!vma || addr + len <= vma->vm_start)) return addr; } @@ -163,24 +165,13 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; - info.high_limit = TASK_SIZE; + info.high_limit = mm->context.asce_limit; addr = vm_unmapped_area(&info); } return addr; } -int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) -{ - if (is_compat_task() || TASK_SIZE >= TASK_MAX_SIZE) - return 0; - if (!(flags & MAP_FIXED)) - addr = 0; - if ((addr + len) >= TASK_SIZE) - return crst_table_upgrade(current->mm); - return 0; -} - static unsigned long s390_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -192,7 +183,8 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr, area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); if (!(area & ~PAGE_MASK)) return area; - if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < TASK_MAX_SIZE) { + if (area == -ENOMEM && !is_compat_task() && + current->mm->context.asce_limit < TASK_SIZE_MAX) { /* Upgrade the page table to 4 levels and retry. */ rc = crst_table_upgrade(mm); if (rc) @@ -214,7 +206,8 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); if (!(area & ~PAGE_MASK)) return area; - if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < TASK_MAX_SIZE) { + if (area == -ENOMEM && !is_compat_task() && + current->mm->context.asce_limit < TASK_SIZE_MAX) { /* Upgrade the page table to 4 levels and retry. */ rc = crst_table_upgrade(mm); if (rc) diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c index 2776bad61094..f502cbe657af 100644 --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -95,7 +95,6 @@ int crst_table_upgrade(struct mm_struct *mm) mm->context.asce_limit = 1UL << 53; mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | _ASCE_USER_BITS | _ASCE_TYPE_REGION2; - mm->task_size = mm->context.asce_limit; spin_unlock_bh(&mm->page_table_lock); on_each_cpu(__crst_table_upgrade, mm, 0); @@ -119,7 +118,6 @@ void crst_table_downgrade(struct mm_struct *mm) mm->context.asce_limit = 1UL << 31; mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT; - mm->task_size = mm->context.asce_limit; crst_table_free(mm, (unsigned long *) pgd); if (current->active_mm == mm) |