[S390] make page table upgrade work again
After TASK_SIZE now gives the current size of the address space the upgrade of a 64 bit process from 3 to 4 levels of page table needs to use the arch_mmap_check hook to catch large mmap lengths. The get_unmapped_area* functions need to check for -ENOMEM from the arch_get_unmapped_area*, upgrade the page table and retry. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>wifi-calibration
parent
f481bfafd3
commit
0fb1d9bcbc
|
@ -22,4 +22,9 @@
|
||||||
#define MCL_CURRENT 1 /* lock all current mappings */
|
#define MCL_CURRENT 1 /* lock all current mappings */
|
||||||
#define MCL_FUTURE 2 /* lock all future mappings */
|
#define MCL_FUTURE 2 /* lock all future mappings */
|
||||||
|
|
||||||
|
#if defined(__KERNEL__) && !defined(__ASSEMBLY__) && defined(CONFIG_64BIT)
|
||||||
|
int s390_mmap_check(unsigned long addr, unsigned long len);
|
||||||
|
#define arch_mmap_check(addr,len,flags) s390_mmap_check(addr,len)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __S390_MMAN_H__ */
|
#endif /* __S390_MMAN_H__ */
|
||||||
|
|
|
@ -89,42 +89,58 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
int s390_mmap_check(unsigned long addr, unsigned long len)
|
||||||
|
{
|
||||||
|
if (!test_thread_flag(TIF_31BIT) &&
|
||||||
|
len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
|
||||||
|
return crst_table_upgrade(current->mm, 1UL << 53);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
s390_get_unmapped_area(struct file *filp, unsigned long addr,
|
s390_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
|
unsigned long area;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||||
if (addr & ~PAGE_MASK)
|
if (!(area & ~PAGE_MASK))
|
||||||
return addr;
|
return area;
|
||||||
if (unlikely(mm->context.asce_limit < addr + len)) {
|
if (area == -ENOMEM &&
|
||||||
rc = crst_table_upgrade(mm, addr + len);
|
!test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
|
||||||
|
/* Upgrade the page table to 4 levels and retry. */
|
||||||
|
rc = crst_table_upgrade(mm, 1UL << 53);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (unsigned long) rc;
|
return (unsigned long) rc;
|
||||||
|
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||||
}
|
}
|
||||||
return addr;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
|
||||||
const unsigned long len, const unsigned long pgoff,
|
const unsigned long len, const unsigned long pgoff,
|
||||||
const unsigned long flags)
|
const unsigned long flags)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
unsigned long addr = addr0;
|
unsigned long area;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
||||||
if (addr & ~PAGE_MASK)
|
if (!(area & ~PAGE_MASK))
|
||||||
return addr;
|
return area;
|
||||||
if (unlikely(mm->context.asce_limit < addr + len)) {
|
if (area == -ENOMEM &&
|
||||||
rc = crst_table_upgrade(mm, addr + len);
|
!test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
|
||||||
|
/* Upgrade the page table to 4 levels and retry. */
|
||||||
|
rc = crst_table_upgrade(mm, 1UL << 53);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (unsigned long) rc;
|
return (unsigned long) rc;
|
||||||
|
area = arch_get_unmapped_area_topdown(filp, addr, len,
|
||||||
|
pgoff, flags);
|
||||||
}
|
}
|
||||||
return addr;
|
return area;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* This function, called very early during the creation of a new
|
* This function, called very early during the creation of a new
|
||||||
|
|
Loading…
Reference in New Issue