aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2012-07-26 08:53:06 +0200
committerBen Hutchings <ben@decadent.org.uk>2012-08-10 00:24:54 +0100
commitf22027d0e8398e377a42a62241137b77a35eda97 (patch)
tree691aacb8ce4a0fb9a72e95744c54fb00e2767d59 /arch/s390/mm
parent60ed9e385606f27c787710bba0dfdb7ff467bdf7 (diff)
s390/mm: downgrade page table after fork of a 31 bit process
commit 0f6f281b731d20bfe75c13f85d33f3f05b440222 upstream. The downgrade of the 4 level page table created by init_new_context is currently done only in start_thread31. If a 31 bit process forks the new mm uses a 4 level page table, including the task size of 2<<42 that goes along with it. This is incorrect as now a 31 bit process can map memory beyond 2GB. Define arch_dup_mmap to do the downgrade after fork. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/mmap.c12
-rw-r--r--arch/s390/mm/pgtable.c5
2 files changed, 10 insertions, 7 deletions
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index a0155c02e32..c70b3d8dea0 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -106,9 +106,15 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
int s390_mmap_check(unsigned long addr, unsigned long len)
{
+ int rc;
+
if (!is_compat_task() &&
- len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
- return crst_table_upgrade(current->mm, 1UL << 53);
+ len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) {
+ rc = crst_table_upgrade(current->mm, 1UL << 53);
+ if (rc)
+ return rc;
+ update_mm(current->mm, current);
+ }
return 0;
}
@@ -128,6 +134,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr,
rc = crst_table_upgrade(mm, 1UL << 53);
if (rc)
return (unsigned long) rc;
+ update_mm(mm, current);
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
}
return area;
@@ -150,6 +157,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
rc = crst_table_upgrade(mm, 1UL << 53);
if (rc)
return (unsigned long) rc;
+ update_mm(mm, current);
area = arch_get_unmapped_area_topdown(filp, addr, len,
pgoff, flags);
}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index f8ceac48cf3..f8e92f831ef 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -97,7 +97,6 @@ repeat:
crst_table_free(mm, table);
if (mm->context.asce_limit < limit)
goto repeat;
- update_mm(mm, current);
return 0;
}
@@ -105,9 +104,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
{
pgd_t *pgd;
- if (mm->context.asce_limit <= limit)
- return;
- __tlb_flush_mm(mm);
while (mm->context.asce_limit > limit) {
pgd = mm->pgd;
switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
@@ -130,7 +126,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
mm->task_size = mm->context.asce_limit;
crst_table_free(mm, (unsigned long *) pgd);
}
- update_mm(mm, current);
}
#endif